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