]> git.sur5r.net Git - openldap/blob - libraries/librewrite/ldapmap.c
First rounded of changes in prep for 2.2.beta3
[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                           *url;
35         LDAPURLDesc                    *lud;
36         int                             attrsonly;
37         char                           *binddn;
38         char                           *bindpw;
39
40 #define MAP_LDAP_EVERYTIME              0x00
41 #define MAP_LDAP_NOW                    0x01
42 #define MAP_LDAP_LATER                  0x02
43         int                             when;
44
45         LDAP                           *ld;
46
47 #ifdef USE_REWRITE_LDAP_PVT_THREADS
48         ldap_pvt_thread_mutex_t         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->url != NULL ) {
60                 free( data->url );
61         }
62
63         if ( data->lud != NULL ) {
64                 ldap_free_urldesc( data->lud );
65         }
66
67         if ( data->binddn != NULL ) {
68                 free( data->binddn );
69         }
70
71         if ( data->bindpw != NULL ) {
72                 free( data->bindpw );
73         }
74
75         if ( data->when != MAP_LDAP_EVERYTIME && data->ld != NULL ) {
76                 ldap_unbind_s( data->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->url = strdup( argv[ 0 ] );
112         if ( data->url == NULL ) {
113                 map_ldap_free( data );
114                 return NULL;
115         }
116         
117         if ( ldap_url_parse( argv[ 0 ], &data->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->url, '/' );
126         assert( p[ 1 ] == '/' );
127         if ( ( p = strchr( p + 2, '/' ) ) != NULL ) {
128                 p[ 0 ] = '\0';
129         }
130
131         if ( strcasecmp( data->lud->lud_attrs[ 0 ], "dn" ) == 0 ) {
132                 data->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->binddn = strdup( p );                     
152                         if ( data->binddn == NULL ) {
153                                 map_ldap_free( data );
154                                 return NULL;
155                         }
156
157                         if ( data->binddn[ l ] == '\"' 
158                                         || data->binddn[ l ] == '\'' ) {
159                                 data->binddn[ l ] = '\0';
160                         }
161                 } else if ( strncasecmp( argv[ 0 ], "bindpw=", 7 ) == 0 ) {
162                         data->bindpw = strdup( argv[ 2 ] + 7 );
163                         if ( data->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->when = MAP_LDAP_NOW;
174                                 
175                                 /*
176                                  * Init LDAP handler ...
177                                  */
178                                 rc = ldap_initialize( &data->ld, data->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->mutex );
186 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
187
188                         } else if ( strcasecmp( p, "later" ) == 0 ) {
189                                 data->when = MAP_LDAP_LATER;
190
191 #ifdef USE_REWRITE_LDAP_PVT_THREADS
192                                 ldap_pvt_thread_mutex_init( &data->mutex );
193 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
194
195                         } else if ( strcasecmp( p, "everytime" ) == 0 ) {
196                                 data->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->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->when == MAP_LDAP_EVERYTIME ) {
233                 rc = ldap_initialize( &ld, data->url );
234         } else {
235 #ifdef USE_REWRITE_LDAP_PVT_THREADS
236                 ldap_pvt_thread_mutex_lock( &data->mutex );
237 #endif /* USE_REWRITE_LDAP_PVT_THREADS */
238
239                 rc = LDAP_SUCCESS;
240
241                 if ( data->when == MAP_LDAP_LATER && data->ld == NULL ) {
242                         rc = ldap_initialize( &data->ld, data->url );
243                 }
244                 
245                 ld = data->ld;
246         }
247
248         if ( rc != LDAP_SUCCESS ) {
249                 rc = REWRITE_ERR;
250                 goto rc_return;
251         }
252
253 do_bind:;
254         if ( data->binddn != NULL ) {
255                 rc = ldap_simple_bind_s( ld, data->binddn, data->bindpw );
256                 if ( rc == LDAP_SERVER_DOWN && first_try ) {
257                         first_try = 0;
258                         if ( ldap_initialize( &ld, data->url ) != LDAP_SUCCESS ) {
259                                 rc = REWRITE_ERR;
260                                 goto rc_return;
261                         }
262                         goto do_bind;
263                 } else if ( rc != REWRITE_SUCCESS ) {
264                         rc = REWRITE_ERR;
265                         goto rc_return;
266                 }
267         }
268
269         rc = ldap_search_s( ld, lud->lud_dn, lud->lud_scope, ( char * )filter,
270                         lud->lud_attrs, data->attrsonly, &res );
271         if ( rc == LDAP_SERVER_DOWN && first_try ) {
272                 first_try = 0;
273                 if ( ldap_initialize( &ld, data->url ) != LDAP_SUCCESS ) {
274                         rc = REWRITE_ERR;
275                         goto rc_return;
276                 }
277                 goto do_bind;
278         } else if ( rc != REWRITE_SUCCESS ) {
279                 rc = REWRITE_ERR;
280                 goto rc_return;
281         }
282
283         if ( ldap_count_entries( ld, res ) != 1 ) {
284                 ldap_msgfree( res );
285                 rc = REWRITE_ERR;
286                 goto rc_return;
287         }
288
289         entry = ldap_first_entry( ld, res );
290         assert( entry != NULL );
291
292         if ( data->attrsonly == 1 ) {
293                 /*
294                  * dn is newly allocated, so there's no need to strdup it
295                  */
296                 val->bv_val = ldap_get_dn( ld, entry );
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->when == MAP_LDAP_EVERYTIME ) {
321                 if ( ld != NULL ) {
322                         ldap_unbind_s( ld );
323                 }
324         } else {
325                 data->ld = ld;
326 #ifdef USE_REWRITE_LDAP_PVT_THREADS
327                 ldap_pvt_thread_mutex_unlock( &data->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         free( data );
347         *pmap = NULL;
348
349         return 0;
350 }
351