]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/config.c
6df5ff97e260f64f175dc47bf6761cac9321a6ea
[openldap] / servers / slapd / back-ldap / config.c
1 /* config.c - ldap backend configuration file routine */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
6  */
7 /* This is an altered version */
8 /*
9  * Copyright 1999, Howard Chu, All rights reserved. <hyc@highlandsun.com>
10  * 
11  * Permission is granted to anyone to use this software for any purpose
12  * on any computer system, and to alter it and redistribute it, subject
13  * to the following restrictions:
14  * 
15  * 1. The author is not responsible for the consequences of use of this
16  *    software, no matter how awful, even if they arise from flaws in it.
17  * 
18  * 2. The origin of this software must not be misrepresented, either by
19  *    explicit claim or by omission.  Since few users ever read sources,
20  *    credits should appear in the documentation.
21  * 
22  * 3. Altered versions must be plainly marked as such, and must not be
23  *    misrepresented as being the original software.  Since few users
24  *    ever read sources, credits should appear in the documentation.
25  * 
26  * 4. This notice may not be removed or altered.
27  *
28  *
29  *
30  * Copyright 2000, Pierangelo Masarati, All rights reserved. <ando@sys-net.it>
31  * 
32  * This software is being modified by Pierangelo Masarati.
33  * The previously reported conditions apply to the modified code as well.
34  * Changes in the original code are highlighted where required.
35  * Credits for the original code go to the author, Howard Chu.
36  */
37
38 #include "portable.h"
39
40 #include <stdio.h>
41
42 #include <ac/string.h>
43 #include <ac/socket.h>
44
45 #include "slap.h"
46 #include "back-ldap.h"
47
48 int
49 ldap_back_db_config(
50     BackendDB   *be,
51     const char  *fname,
52     int         lineno,
53     int         argc,
54     char        **argv
55 )
56 {
57         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
58
59         if ( li == NULL ) {
60                 fprintf( stderr, "%s: line %d: ldap backend info is null!\n",
61                     fname, lineno );
62                 return( 1 );
63         }
64
65         /* server address to query (depricated, use "uri" directive) */
66         if ( strcasecmp( argv[0], "server" ) == 0 ) {
67                 if (argc != 2) {
68                         fprintf( stderr,
69         "%s: line %d: missing address in \"server <address>\" line\n",
70                             fname, lineno );
71                         return( 1 );
72                 }
73                 if (li->url != NULL)
74                         ch_free(li->url);
75                 li->url = ch_calloc(strlen(argv[1]) + 9, sizeof(char));
76                 if (li->url != NULL) {
77                         strcpy(li->url, "ldap://");
78                         strcat(li->url, argv[1]);
79                         strcat(li->url, "/");
80                 }
81
82         /* URI of server to query (preferred over "server" directive) */
83         } else if ( strcasecmp( argv[0], "uri" ) == 0 ) {
84                 if (argc != 2) {
85                         fprintf( stderr,
86         "%s: line %d: missing address in \"uri <address>\" line\n",
87                             fname, lineno );
88                         return( 1 );
89                 }
90                 if (li->url != NULL)
91                         ch_free(li->url);
92                 li->url = ch_strdup(argv[1]);
93
94         /* name to use for ldap_back_group */
95         } else if ( strcasecmp( argv[0], "binddn" ) == 0 ) {
96                 if (argc != 2) {
97                         fprintf( stderr,
98         "%s: line %d: missing name in \"binddn <name>\" line\n",
99                             fname, lineno );
100                         return( 1 );
101                 }
102                 li->binddn = ch_strdup(argv[1]);
103
104         /* password to use for ldap_back_group */
105         } else if ( strcasecmp( argv[0], "bindpw" ) == 0 ) {
106                 if (argc != 2) {
107                         fprintf( stderr,
108         "%s: line %d: missing password in \"bindpw <password>\" line\n",
109                             fname, lineno );
110                         return( 1 );
111                 }
112                 li->bindpw = ch_strdup(argv[1]);
113         
114         /* save bind creds for referral rebinds? */
115         } else if ( strcasecmp( argv[0], "rebind-as-user" ) == 0 ) {
116                 if (argc != 1) {
117                         fprintf( stderr,
118         "%s: line %d: rebind-as-user takes no arguments\n",
119                             fname, lineno );
120                         return( 1 );
121                 }
122                 li->savecred = 1;
123         
124         /* dn massaging */
125         } else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
126                 BackendDB *tmp_be;
127                 struct berval bvnc, *nvnc = NULL, *pvnc = NULL, 
128                         brnc, *nrnc = NULL, *prnc = NULL;
129 #ifdef ENABLE_REWRITE
130                 int rc;
131 #endif /* ENABLE_REWRITE */
132                 
133                 /*
134                  * syntax:
135                  * 
136                  *      suffixmassage <suffix> <massaged suffix>
137                  *
138                  * the <suffix> field must be defined as a valid suffix
139                  * (or suffixAlias?) for the current database;
140                  * the <massaged suffix> shouldn't have already been
141                  * defined as a valid suffix or suffixAlias for the 
142                  * current server
143                  */
144                 if ( argc != 3 ) {
145                         fprintf( stderr, "%s: line %d: syntax is"
146                                        " \"suffixMassage <suffix>"
147                                        " <massaged suffix>\"\n",
148                                 fname, lineno );
149                         return( 1 );
150                 }
151                 
152                 ber_str2bv( argv[1], 0, 0, &bvnc );
153                 pvnc = (struct berval *)ber_memalloc( sizeof( struct berval ) );
154                 nvnc = (struct berval *)ber_memalloc( sizeof( struct berval ) );
155                 if ( dnPrettyNormal( NULL, &bvnc, pvnc, nvnc ) != LDAP_SUCCESS ) {
156                         fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
157                                 fname, lineno, bvnc.bv_val );
158                         return( 1 );
159                 }
160                 tmp_be = select_backend( nvnc, 0, 0 );
161                 if ( tmp_be != NULL && tmp_be != be ) {
162                         fprintf( stderr, "%s: line %d: suffix already in use"
163                                        " by another backend in"
164                                        " \"suffixMassage <suffix>"
165                                        " <massaged suffix>\"\n",
166                                 fname, lineno );
167                         ber_bvfree( nvnc );
168                         ber_bvfree( pvnc );
169                         return( 1 );
170                 }
171
172                 ber_str2bv( argv[2], 0, 0, &brnc );
173                 prnc = (struct berval *)ber_memalloc( sizeof( struct berval ) );
174                 nrnc = (struct berval *)ber_memalloc( sizeof( struct berval ) );
175                 if ( dnPrettyNormal( NULL, &brnc, prnc, nrnc ) != LDAP_SUCCESS ) {
176                         fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
177                                 fname, lineno, brnc.bv_val );
178                         ber_bvfree( nvnc );
179                         ber_bvfree( pvnc );
180                         return( 1 );
181                 }
182
183 #if 0
184                 tmp_be = select_backend( &nrnc, 0, 0 );
185                 if ( tmp_be != NULL ) {
186                         fprintf( stderr, "%s: line %d: massaged suffix"
187                                        " already in use by another backend in" 
188                                        " \"suffixMassage <suffix>"
189                                        " <massaged suffix>\"\n",
190                                 fname, lineno );
191                         ber_bvfree( nvnc );
192                         ber_bvfree( pvnc );
193                         ber_bvfree( nrnc );
194                         ber_bvfree( prnc );
195                         return( 1 );
196                 }
197 #endif
198
199 #ifdef ENABLE_REWRITE
200                 /*
201                  * The suffix massaging is emulated by means of the
202                  * rewrite capabilities
203                  * FIXME: no extra rewrite capabilities should be added
204                  * to the database
205                  */
206                 rc = suffix_massage_config( li->rwinfo, pvnc, nvnc, prnc, nrnc );
207
208                 ber_bvfree( nvnc );
209                 ber_bvfree( pvnc );
210                 ber_bvfree( nrnc );
211                 ber_bvfree( prnc );
212
213                 return( rc );
214
215 #else /* !ENABLE_REWRITE */
216                 ber_bvarray_add( &li->suffix_massage, pvnc );
217                 ber_bvarray_add( &li->suffix_massage, nvnc );
218                 
219                 ber_bvarray_add( &li->suffix_massage, prnc );
220                 ber_bvarray_add( &li->suffix_massage, nrnc );
221 #endif /* !ENABLE_REWRITE */
222
223         /* rewrite stuff ... */
224         } else if ( strncasecmp( argv[0], "rewrite", 7 ) == 0 ) {
225 #ifdef ENABLE_REWRITE
226                 return rewrite_parse( li->rwinfo, fname, lineno, argc, argv );
227
228 #else /* !ENABLE_REWRITE */
229                 fprintf( stderr, "%s: line %d: rewrite capabilities "
230                                 "are not enabled\n", fname, lineno );
231 #endif /* !ENABLE_REWRITE */
232                 
233         /* objectclass/attribute mapping */
234         } else if ( strcasecmp( argv[0], "map" ) == 0 ) {
235                 struct ldapmap *map;
236                 struct ldapmapping *mapping;
237                 char *src, *dst;
238
239                 if ( argc < 3 || argc > 4 ) {
240                         fprintf( stderr,
241         "%s: line %d: syntax is \"map {objectclass | attribute} {<source> | *} [<dest> | *]\"\n",
242                                 fname, lineno );
243                         return( 1 );
244                 }
245
246                 if ( strcasecmp( argv[1], "objectclass" ) == 0 ) {
247                         map = &li->oc_map;
248                 } else if ( strcasecmp( argv[1], "attribute" ) == 0 ) {
249                         map = &li->at_map;
250                 } else {
251                         fprintf( stderr, "%s: line %d: syntax is "
252                                 "\"map {objectclass | attribute} {<source> | *} "
253                                         "[<dest> | *]\"\n",
254                                 fname, lineno );
255                         return( 1 );
256                 }
257
258                 if ( strcasecmp( argv[2], "*" ) != 0 ) {
259                         src = argv[2];
260                         if ( argc < 4 )
261                                 dst = "";
262                         else if ( strcasecmp( argv[3], "*" ) == 0 )
263                                 dst = src;
264                         else
265                                 dst = argv[3];
266                 } else {
267                         if ( argc < 4 ) {
268                                 map->drop_missing = 1;
269                                 return 0;
270                         }
271                         if ( strcasecmp( argv[3], "*" ) == 0 ) {
272                                 map->drop_missing = 0;
273                                 return 0;
274                         }
275
276                         src = argv[3];
277                         dst = src;
278                 }
279
280                 if ( ( map == &li->at_map )
281                         && ( strcasecmp( src, "objectclass" ) == 0
282                                 || strcasecmp( dst, "objectclass" ) == 0 ) )
283                 {
284                         fprintf( stderr,
285                                 "%s: line %d: objectclass attribute cannot be mapped\n",
286                                 fname, lineno );
287                 }
288
289                 mapping = (struct ldapmapping *)ch_calloc( 2,
290                         sizeof(struct ldapmapping) );
291                 if ( mapping == NULL ) {
292                         fprintf( stderr,
293                                 "%s: line %d: out of memory\n",
294                                 fname, lineno );
295                         return( 1 );
296                 }
297                 ber_str2bv( src, 0, 1, &mapping->src );
298                 ber_str2bv( dst, 0, 1, &mapping->dst );
299                 if ( *dst != 0 ) {
300                         mapping[1].src = mapping->dst;
301                         mapping[1].dst = mapping->src;
302                 } else {
303                         mapping[1].src = mapping->src;
304                         mapping[1].dst = mapping->dst;
305                 }
306
307                 if ( avl_find( map->map, (caddr_t)mapping, mapping_cmp ) != NULL ||
308                         avl_find( map->remap, (caddr_t)&mapping[1], mapping_cmp ) != NULL)
309                 {
310                         fprintf( stderr,
311                                 "%s: line %d: duplicate mapping found (ignored)\n",
312                                 fname, lineno );
313                         return 0;
314                 }
315
316                 avl_insert( &map->map, (caddr_t)mapping,
317                                         mapping_cmp, mapping_dup );
318                 avl_insert( &map->remap, (caddr_t)&mapping[1],
319                                         mapping_cmp, mapping_dup );
320
321         /* anything else */
322         } else {
323                 fprintf( stderr, "%s: line %d: unknown directive \"%s\" "
324                         "in ldap database definition (ignored)\n",
325                     fname, lineno, argv[0] );
326         }
327         return 0;
328 }
329
330 #ifdef ENABLE_REWRITE
331 static char *
332 suffix_massage_regexize( const char *s )
333 {
334         char *res, *ptr;
335         const char *p, *r;
336         int i;
337
338         for ( i = 0, p = s; 
339                         ( r = strchr( p, ',' ) ) != NULL; 
340                         p = r + 1, i++ )
341                 ;
342
343         res = ch_calloc( sizeof( char ), strlen( s ) + 4 + 4*i + 1 );
344
345         ptr = slap_strcopy( res, "(.*)" );
346         for ( i = 0, p = s;
347                         ( r = strchr( p, ',' ) ) != NULL;
348                         p = r + 1 , i++ ) {
349                 ptr = slap_strncopy( ptr, p, r - p + 1 );
350                 ptr = slap_strcopy( ptr, "[ ]?" );
351
352                 if ( r[ 1 ] == ' ' ) {
353                         r++;
354                 }
355         }
356         slap_strcopy( ptr, p );
357
358         return res;
359 }
360
361 static char *
362 suffix_massage_patternize( const char *s )
363 {
364         ber_len_t       len;
365         char            *res;
366
367         len = strlen( s );
368
369         res = ch_calloc( sizeof( char ), len + sizeof( "%1" ) );
370         if ( res == NULL ) {
371                 return NULL;
372         }
373
374         strcpy( res, "%1" );
375         strcpy( res + sizeof( "%1" ) - 1, s );
376
377         return res;
378 }
379
380 int
381 suffix_massage_config( 
382                 struct rewrite_info *info,
383                 struct berval *pvnc,
384                 struct berval *nvnc,
385                 struct berval *prnc,
386                 struct berval *nrnc
387 )
388 {
389         char *rargv[ 5 ];
390         int line = 0;
391
392         rargv[ 0 ] = "rewriteEngine";
393         rargv[ 1 ] = "on";
394         rargv[ 2 ] = NULL;
395         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
396
397         rargv[ 0 ] = "rewriteContext";
398         rargv[ 1 ] = "default";
399         rargv[ 2 ] = NULL;
400         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
401
402         rargv[ 0 ] = "rewriteRule";
403         rargv[ 1 ] = suffix_massage_regexize( pvnc->bv_val );
404         rargv[ 2 ] = suffix_massage_patternize( prnc->bv_val );
405         rargv[ 3 ] = ":";
406         rargv[ 4 ] = NULL;
407         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
408         ch_free( rargv[ 1 ] );
409         ch_free( rargv[ 2 ] );
410         
411         rargv[ 0 ] = "rewriteContext";
412         rargv[ 1 ] = "searchResult";
413         rargv[ 2 ] = NULL;
414         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
415         
416         rargv[ 0 ] = "rewriteRule";
417         rargv[ 1 ] = suffix_massage_regexize( prnc->bv_val );
418         rargv[ 2 ] = suffix_massage_patternize( pvnc->bv_val );
419         rargv[ 3 ] = ":";
420         rargv[ 4 ] = NULL;
421         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
422         ch_free( rargv[ 1 ] );
423         ch_free( rargv[ 2 ] );
424
425         /*
426          * the filter should be rewritten as
427          * 
428          * rewriteRule
429          *      "(.*)member=([^)]+),o=Foo Bar,[ ]?c=US(.*)"
430          *      "%1member=%2,dc=example,dc=com%3"
431          *
432          * where "o=Foo Bar, c=US" is the virtual naming context,
433          * and "dc=example, dc=com" is the real naming context
434          */
435         rargv[ 0 ] = "rewriteContext";
436         rargv[ 1 ] = "searchFilter";
437         rargv[ 2 ] = NULL;
438         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
439
440 #if 1 /* rewrite filters */
441         {
442                 /*
443                  * Note: this is far more optimistic than desirable:
444                  * for any AVA value ending with the virtual naming
445                  * context the terminal part will be replaced by the
446                  * real naming context; a better solution would be to
447                  * walk the filter looking for DN-valued attributes,
448                  * and only rewrite those that require rewriting
449                  */
450                 char vbuf[LDAP_FILT_MAXSIZ], rbuf[LDAP_FILT_MAXSIZ];
451
452                 snprintf( vbuf, sizeof( vbuf ), "(.*)%s\\)(.*)", nvnc->bv_val );
453                 snprintf( rbuf, sizeof( rbuf ), "%%1%s)%%2", nrnc->bv_val );
454                 
455                 rargv[ 0 ] = "rewriteRule";
456                 rargv[ 1 ] = vbuf;
457                 rargv[ 2 ] = rbuf;
458                 rargv[ 3 ] = ":";
459                 rargv[ 4 ] = NULL;
460                 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
461         }
462 #endif /* rewrite filters */
463
464 #if 0 /*  "matched" is not normalized */
465         rargv[ 0 ] = "rewriteContext";
466         rargv[ 1 ] = "matchedDn";
467         rargv[ 2 ] = "alias";
468         rargv[ 3 ] = "searchResult";
469         rargv[ 4 ] = NULL;
470         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
471 #else /* normalize "matched" */
472         rargv[ 0 ] = "rewriteContext";
473         rargv[ 1 ] = "matchedDn";
474         rargv[ 2 ] = NULL;
475         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
476
477         rargv[ 0 ] = "rewriteRule";
478         rargv[ 1 ] = suffix_massage_regexize( prnc->bv_val );
479         rargv[ 2 ] = suffix_massage_patternize( nvnc->bv_val );
480         rargv[ 3 ] = ":";
481         rargv[ 4 ] = NULL;
482         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
483         ch_free( rargv[ 1 ] );
484         ch_free( rargv[ 2 ] );
485 #endif /* normalize "matched" */
486
487         return 0;
488 }
489 #endif /* ENABLE_REWRITE */