]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/config.c
2cc55fec88d4845f4948267b3a96f9977da1247c
[openldap] / servers / slapd / back-ldap / config.c
1 /* config.c - ldap backend configuration file routine */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003-2005 The OpenLDAP Foundation.
6  * Portions Copyright 1999-2003 Howard Chu.
7  * Portions Copyright 2000-2003 Pierangelo Masarati.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS:
19  * This work was initially developed by the Howard Chu for inclusion
20  * in OpenLDAP Software and subsequently enhanced by Pierangelo
21  * Masarati.
22  */
23
24 #include "portable.h"
25
26 #include <stdio.h>
27
28 #include <ac/string.h>
29 #include <ac/ctype.h>
30 #include <ac/socket.h>
31
32 #include "slap.h"
33 #include "config.h"
34 #include "back-ldap.h"
35 #include "lutil.h"
36 #include "ldif.h"
37 #undef ldap_debug
38 /* for advanced URL parsing */
39 #include "../../../libraries/libldap/ldap-int.h"
40
41 static SLAP_EXTOP_MAIN_FN ldap_back_exop_whoami;
42
43 static ConfigDriver ldap_back_cf_gen;
44
45 enum {
46         LDAP_BACK_CFG_URI = 1,
47         LDAP_BACK_CFG_TLS,
48         LDAP_BACK_CFG_ACL_AUTHCDN,
49         LDAP_BACK_CFG_ACL_PASSWD,
50         LDAP_BACK_CFG_ACL_METHOD,
51         LDAP_BACK_CFG_ACL_BIND,
52         LDAP_BACK_CFG_IDASSERT_MODE,
53         LDAP_BACK_CFG_IDASSERT_AUTHCDN,
54         LDAP_BACK_CFG_IDASSERT_PASSWD,
55         LDAP_BACK_CFG_IDASSERT_AUTHZFROM,
56         LDAP_BACK_CFG_IDASSERT_METHOD,
57         LDAP_BACK_CFG_IDASSERT_BIND,
58         LDAP_BACK_CFG_REBIND,
59         LDAP_BACK_CFG_CHASE,
60         LDAP_BACK_CFG_T_F,
61         LDAP_BACK_CFG_WHOAMI,
62         LDAP_BACK_CFG_TIMEOUT,
63         LDAP_BACK_CFG_REWRITE
64 };
65
66 static ConfigTable ldapcfg[] = {
67         { "uri", "uri", 2, 2, 0,
68                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_URI,
69                 ldap_back_cf_gen, "( OLcfgDbAt:0.14 "
70                         "NAME 'olcDbURI' "
71                         "DESC 'URI (list) for remote DSA' "
72                         "SYNTAX OMsDirectoryString "
73                         "SINGLE-VALUE )",
74                 NULL, NULL },
75         { "tls", "what", 2, 2, 0,
76                 ARG_MAGIC|LDAP_BACK_CFG_TLS,
77                 ldap_back_cf_gen, "( OLcfgDbAt:3.1 "
78                         "NAME 'olcDbStartTLS' "
79                         "DESC 'StartTLS' "
80                         "SYNTAX OMsDirectoryString "
81                         "SINGLE-VALUE )",
82                 NULL, NULL },
83         { "acl-authcDN", "DN", 2, 2, 0,
84                 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_ACL_AUTHCDN,
85                 ldap_back_cf_gen, "( OLcfgDbAt:3.2 "
86                         "NAME 'olcDbACLAuthcDn' "
87                         "DESC 'Remote ACL administrative identity' "
88                         "OBSOLETE "
89                         "SYNTAX OMsDN "
90                         "SINGLE-VALUE )",
91                 NULL, NULL },
92         /* deprecated, will be removed; aliases "acl-authcDN" */
93         { "binddn", "DN", 2, 2, 0,
94                 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_ACL_AUTHCDN,
95                 ldap_back_cf_gen, NULL, NULL, NULL },
96         { "acl-passwd", "cred", 2, 2, 0,
97                 ARG_MAGIC|LDAP_BACK_CFG_ACL_PASSWD,
98                 ldap_back_cf_gen, "( OLcfgDbAt:3.3 "
99                         "NAME 'olcDbACLPasswd' "
100                         "DESC 'Remote ACL administrative identity credentials' "
101                         "OBSOLETE "
102                         "SYNTAX OMsDirectoryString "
103                         "SINGLE-VALUE )",
104                 NULL, NULL },
105         /* deprecated, will be removed; aliases "acl-passwd" */
106         { "bindpw", "cred", 2, 2, 0,
107                 ARG_MAGIC|LDAP_BACK_CFG_ACL_PASSWD,
108                 ldap_back_cf_gen, NULL, NULL, NULL },
109         /* deprecated, will be removed; aliases "acl-bind" */
110         { "acl-method", "args", 2, 0, 0,
111                 ARG_MAGIC|LDAP_BACK_CFG_ACL_METHOD,
112                 ldap_back_cf_gen, NULL, NULL, NULL },
113         { "acl-bind", "args", 2, 0, 0,
114                 ARG_MAGIC|LDAP_BACK_CFG_ACL_BIND,
115                 ldap_back_cf_gen, "( OLcfgDbAt:3.4 "
116                         "NAME 'olcDbACLBind' "
117                         "DESC 'Remote ACL administrative identity auth bind configuration' "
118                         "SYNTAX OMsDirectoryString "
119                         "SINGLE-VALUE )",
120                 NULL, NULL },
121         { "idassert-authcDN", "DN", 2, 2, 0,
122                 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHCDN,
123                 ldap_back_cf_gen, "( OLcfgDbAt:3.5 "
124                         "NAME 'olcDbIDAssertAuthcDn' "
125                         "DESC 'Remote Identity Assertion administrative identity' "
126                         "OBSOLETE "
127                         "SYNTAX OMsDN "
128                         "SINGLE-VALUE )",
129                 NULL, NULL },
130         /* deprecated, will be removed; partially aliases "idassert-authcDN" */
131         { "proxyauthzdn", "DN", 2, 2, 0,
132                 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHCDN,
133                 ldap_back_cf_gen, NULL, NULL, NULL },
134         { "idassert-passwd", "cred", 2, 2, 0,
135                 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_PASSWD,
136                 ldap_back_cf_gen, "( OLcfgDbAt:3.6 "
137                         "NAME 'olcDbIDAssertPasswd' "
138                         "DESC 'Remote Identity Assertion administrative identity credentials' "
139                         "OBSOLETE "
140                         "SYNTAX OMsDirectoryString "
141                         "SINGLE-VALUE )",
142                 NULL, NULL },
143         /* deprecated, will be removed; partially aliases "idassert-passwd" */
144         { "proxyauthzpw", "cred", 2, 2, 0,
145                 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_PASSWD,
146                 ldap_back_cf_gen, NULL, NULL, NULL },
147         { "idassert-bind", "args", 2, 0, 0,
148                 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND,
149                 ldap_back_cf_gen, "( OLcfgDbAt:3.7 "
150                         "NAME 'olcDbIDAssertBind' "
151                         "DESC 'Remote Identity Assertion administrative identity auth bind configuration' "
152                         "SYNTAX OMsDirectoryString "
153                         "SINGLE-VALUE )",
154                 NULL, NULL },
155         { "idassert-method", "args", 2, 0, 0,
156                 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_METHOD,
157                 ldap_back_cf_gen, NULL, NULL, NULL },
158         { "idassert-mode", "mode>|u:<user>|[dn:]<DN", 2, 0, 0,
159                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_MODE,
160                 ldap_back_cf_gen, "( OLcfgDbAt:3.8 "
161                         "NAME 'olcDbIDAssertMode' "
162                         "DESC 'Remote Identity Assertion mode' "
163                         "OBSOLETE "
164                         "SYNTAX OMsDirectoryString "
165                         "SINGLE-VALUE)",
166                 NULL, NULL },
167         { "idassert-authzFrom", "authzRule", 2, 2, 0,
168                 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHZFROM,
169                 ldap_back_cf_gen, "( OLcfgDbAt:3.9 "
170                         "NAME 'olcDbIDAssertAuthzFrom' "
171                         "DESC 'Remote Identity Assertion authz rules' "
172                         "SYNTAX OMsDirectoryString "
173                         "X-ORDERED 'VALUES' )",
174                 NULL, NULL },
175         { "rebind-as-user", "NO|yes", 1, 2, 0,
176                 ARG_MAGIC|LDAP_BACK_CFG_REBIND,
177                 ldap_back_cf_gen, "( OLcfgDbAt:3.10 "
178                         "NAME 'olcDbRebindAsUser' "
179                         "DESC 'Rebind as user' "
180                         "SYNTAX OMsDirectoryString "
181                         "SINGLE-VALUE )",
182                 NULL, NULL },
183         { "chase-referrals", "YES|no", 2, 2, 0,
184                 ARG_MAGIC|LDAP_BACK_CFG_CHASE,
185                 ldap_back_cf_gen, "( OLcfgDbAt:3.11 "
186                         "NAME 'olcDbChaseReferrals' "
187                         "DESC 'Chase referrals' "
188                         "SYNTAX OMsDirectoryString "
189                         "SINGLE-VALUE )",
190                 NULL, NULL },
191         { "t-f-support", "NO|yes|discover", 2, 2, 0,
192                 ARG_MAGIC|LDAP_BACK_CFG_T_F,
193                 ldap_back_cf_gen, "( OLcfgDbAt:3.12 "
194                         "NAME 'olcDbTFSupport' "
195                         "DESC 'Absolute filters support' "
196                         "SYNTAX OMsDirectoryString "
197                         "SINGLE-VALUE )",
198                 NULL, NULL },
199         { "proxy-whoami", "NO|yes", 1, 2, 0,
200                 ARG_MAGIC|LDAP_BACK_CFG_WHOAMI,
201                 ldap_back_cf_gen, "( OLcfgDbAt:3.13 "
202                         "NAME 'olcDbProxyWhoAmI' "
203                         "DESC 'Proxy whoAmI exop' "
204                         "SYNTAX OMsDirectoryString "
205                         "SINGLE-VALUE )",
206                 NULL, NULL },
207         { "timeout", "timeout", 0, 2, 0,
208                 ARG_MAGIC|LDAP_BACK_CFG_TIMEOUT,
209                 ldap_back_cf_gen, "( OLcfgDbAt:3.14 "
210                         "NAME 'olcDbTimeout' "
211                         "DESC 'Per-operation timeouts' "
212                         "SYNTAX OMsDirectoryString "
213                         "SINGLE-VALUE )",
214                 NULL, NULL },
215         { "suffixmassage", "[virtual]> <real", 2, 3, 0,
216                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
217                 ldap_back_cf_gen, NULL, NULL, NULL },
218         { "map", "attribute|objectClass> [*|<local>] *|<remote", 3, 4, 0,
219                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
220                 ldap_back_cf_gen, NULL, NULL, NULL },
221         { "rewrite", "<arglist>", 2, 4, STRLENOF( "rewrite" ),
222                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
223                 ldap_back_cf_gen, NULL, NULL, NULL },
224         { NULL, NULL, 0, 0, 0, ARG_IGNORED,
225                 NULL, NULL, NULL, NULL }
226 };
227
228 static ConfigOCs ldapocs[] = {
229         { "( OLcfgDbOc:3.1 "
230                 "NAME 'olcLDAPConfig' "
231                 "DESC 'LDAP backend configuration' "
232                 "SUP olcDatabaseConfig "
233                 "MUST olcDbURI "
234                 "MAY ( olcDbStartTLS "
235                         "$ olcDbACLAuthcDn "
236                         "$ olcDbACLPasswd "
237                         "$ olcDbACLBind "
238                         "$ olcDbIDAssertAuthcDn "
239                         "$ olcDbIDAssertPasswd "
240                         "$ olcDbIDAssertBind "
241                         "$ olcDbIDAssertMode "
242                         "$ olcDbIDAssertAuthzFrom "
243                         "$ olcDbRebindAsUser "
244                         "$ olcDbChaseReferrals "
245                         "$ olcDbTFSupport "
246                         "$ olcDbProxyWhoAmI "
247                         "$ olcDbTimeout "
248                 ") )",
249                         Cft_Database, ldapcfg},
250         { NULL, 0, NULL }
251 };
252
253 #define LDAP_BACK_C_NO                  (0x0U)
254 #define LDAP_BACK_C_YES                 (0x1U)
255 static slap_verbmasks yn_mode[] = {
256         { BER_BVC( "yes" ),             LDAP_BACK_C_YES},
257         { BER_BVC( "no" ),              LDAP_BACK_C_NO },
258         { BER_BVNULL,                   0 }
259 };
260
261 static slap_verbmasks idassert_mode[] = {
262         { BER_BVC("self"),              LDAP_BACK_IDASSERT_SELF },
263         { BER_BVC("anonymous"),         LDAP_BACK_IDASSERT_ANONYMOUS },
264         { BER_BVC("none"),              LDAP_BACK_IDASSERT_NOASSERT },
265         { BER_BVC("legacy"),            LDAP_BACK_IDASSERT_LEGACY },
266         { BER_BVNULL,                   0 }
267 };
268
269 static slap_verbmasks tls_mode[] = {
270         { BER_BVC( "propagate" ),       LDAP_BACK_F_TLS_PROPAGATE_MASK },
271         { BER_BVC( "try-propagate" ),   LDAP_BACK_F_PROPAGATE_TLS },
272         { BER_BVC( "start" ),           LDAP_BACK_F_TLS_USE_MASK },
273         { BER_BVC( "try-start" ),       LDAP_BACK_F_USE_TLS },
274         { BER_BVC( "none" ),            LDAP_BACK_C_NO },
275         { BER_BVNULL,                   0 }
276 };
277
278 static slap_verbmasks t_f_mode[] = {
279         { BER_BVC( "yes" ),             LDAP_BACK_F_SUPPORT_T_F },
280         { BER_BVC( "discover" ),        LDAP_BACK_F_SUPPORT_T_F_DISCOVER },
281         { BER_BVC( "no" ),              LDAP_BACK_C_NO },
282         { BER_BVNULL,                   0 }
283 };
284
285 static slap_cf_aux_table timeout_table[] = {
286         { BER_BVC("add="), 0 * sizeof( time_t ), 'u', 0, NULL },
287         { BER_BVC("delete="), 1 * sizeof( time_t ), 'u', 0, NULL },
288         { BER_BVC("modify="), 2 * sizeof( time_t ), 'u', 0, NULL },
289         { BER_BVC("modrdn="), 3 * sizeof( time_t ), 'u', 0, NULL },
290         { BER_BVNULL, 0, 0, 0, NULL }
291 };
292
293 static int
294 ldap_back_cf_gen( ConfigArgs *c )
295 {
296         ldapinfo_t      *li = ( ldapinfo_t * )c->be->be_private;
297         int             rc;
298         int             i;
299
300         if ( c->op == SLAP_CONFIG_EMIT ) {
301                 struct berval   bv = BER_BVNULL;
302                 rc = 0;
303
304                 switch( c->type ) {
305                 case LDAP_BACK_CFG_URI:
306                         if ( li->li_uri != NULL ) {
307                                 c->value_string = ch_strdup( li->li_uri );
308
309                         } else {
310                                 rc = 1;
311                         }
312                         break;
313
314                 case LDAP_BACK_CFG_TLS:
315                         enum_to_verb( tls_mode, ( li->li_flags & LDAP_BACK_F_TLS_MASK ), &bv );
316                         if ( BER_BVISNULL( &bv ) ) {
317                                 /* there's something wrong... */
318                                 assert( 0 );
319                                 rc = 1;
320
321                         } else {
322                                 value_add_one( &c->rvalue_vals, &bv );
323                         }
324                         break;
325
326                 case LDAP_BACK_CFG_ACL_AUTHCDN:
327                 case LDAP_BACK_CFG_ACL_PASSWD:
328                 case LDAP_BACK_CFG_ACL_METHOD:
329                         /* handled by LDAP_BACK_CFG_ACL_BIND */
330                         rc = 1;
331                         break;
332
333                 case LDAP_BACK_CFG_ACL_BIND: {
334                         int     i;
335
336                         bindconf_unparse( &li->li_acl, &bv );
337
338                         for ( i = 0; isspace( bv.bv_val[ i ] ); i++ )
339                                 /* count spaces */ ;
340
341                         if ( i ) {
342                                 bv.bv_len -= i;
343                                 AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ],
344                                         bv.bv_len + 1 );
345                         }
346
347                         ber_bvarray_add( &c->rvalue_vals, &bv );
348                         break;
349                 }
350
351                 case LDAP_BACK_CFG_IDASSERT_MODE:
352                 case LDAP_BACK_CFG_IDASSERT_AUTHCDN:
353                 case LDAP_BACK_CFG_IDASSERT_PASSWD:
354                 case LDAP_BACK_CFG_IDASSERT_METHOD:
355                         /* handled by LDAP_BACK_CFG_IDASSERT_BIND */
356                         rc = 1;
357                         break;
358
359                 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
360                         int             i;
361
362                         if ( li->li_idassert_authz == NULL ) {
363                                 rc = 1;
364                                 break;
365                         }
366
367                         for ( i = 0; !BER_BVISNULL( &li->li_idassert_authz[ i ] ); i++ )
368                         {
369                                 value_add_one( &c->rvalue_vals, &li->li_idassert_authz[ i ] );
370                         }
371                         break;
372                 }
373
374                 case LDAP_BACK_CFG_IDASSERT_BIND: {
375                         int             i;
376                         struct berval   bc = BER_BVNULL;
377                         char            *ptr;
378
379                         if ( li->li_idassert_authmethod != LDAP_AUTH_NONE ) {
380                                 ber_len_t       len;
381
382                                 switch ( li->li_idassert_mode ) {
383                                 case LDAP_BACK_IDASSERT_OTHERID:
384                                 case LDAP_BACK_IDASSERT_OTHERDN:
385                                         break;
386
387                                 default: {
388                                         struct berval   mode = BER_BVNULL;
389
390                                         enum_to_verb( idassert_mode, li->li_idassert_mode, &mode );
391                                         if ( BER_BVISNULL( &mode ) ) {
392                                                 /* there's something wrong... */
393                                                 assert( 0 );
394                                                 rc = 1;
395         
396                                         } else {
397                                                 bv.bv_len = STRLENOF( "mode=" ) + mode.bv_len;
398                                                 bv.bv_val = ch_malloc( bv.bv_len + 1 );
399
400                                                 ptr = lutil_strcopy( bv.bv_val, "mode=" );
401                                                 ptr = lutil_strcopy( ptr, mode.bv_val );
402                                         }
403                                         break;
404                                 }
405                                 }
406
407                                 if ( li->li_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) {
408                                         len = bv.bv_len + STRLENOF( "authz=native" );
409
410                                         if ( !BER_BVISEMPTY( &bv ) ) {
411                                                 len += STRLENOF( " " );
412                                         }
413
414                                         bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
415
416                                         ptr = &bv.bv_val[ bv.bv_len ];
417
418                                         if ( !BER_BVISEMPTY( &bv ) ) {
419                                                 ptr = lutil_strcopy( ptr, " " );
420                                         }
421
422                                         (void)lutil_strcopy( ptr, "authz=native" );
423                                 }
424
425                                 len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override" );
426                                 /* flags */
427                                 if ( !BER_BVISEMPTY( &bv ) ) {
428                                         len += STRLENOF( " " );
429                                 }
430
431                                 bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
432
433                                 ptr = &bv.bv_val[ bv.bv_len ];
434
435                                 if ( !BER_BVISEMPTY( &bv ) ) {
436                                         ptr = lutil_strcopy( ptr, " " );
437                                 }
438
439                                 ptr = lutil_strcopy( ptr, "flags=" );
440
441                                 if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
442                                         ptr = lutil_strcopy( ptr, "prescriptive" );
443                                 } else {
444                                         ptr = lutil_strcopy( ptr, "non-prescriptive" );
445                                 }
446
447                                 if ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
448                                         ptr = lutil_strcopy( ptr, ",override" );
449                                 }
450
451                                 bv.bv_len = ( ptr - bv.bv_val );
452                                 /* end-of-flags */
453                         }
454
455                         bindconf_unparse( &li->li_idassert, &bc );
456
457                         if ( !BER_BVISNULL( &bv ) ) {
458                                 ber_len_t       len = bv.bv_len + bc.bv_len;
459
460                                 bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
461
462                                 assert( bc.bv_val[ 0 ] == ' ' );
463
464                                 ptr = lutil_strcopy( &bv.bv_val[ bv.bv_len ], bc.bv_val );
465                                 free( bc.bv_val );
466                                 bv.bv_len = ptr - bv.bv_val;
467
468                         } else {
469                                 for ( i = 0; isspace( bc.bv_val[ i ] ); i++ )
470                                         /* count spaces */ ;
471
472                                 if ( i ) {
473                                         bc.bv_len -= i;
474                                         AC_MEMCPY( bc.bv_val, &bc.bv_val[ i ], bc.bv_len + 1 );
475                                 }
476
477                                 bv = bc;
478                         }
479                         
480                         ber_bvarray_add( &c->rvalue_vals, &bv );
481
482                         break;
483                 }
484
485                 case LDAP_BACK_CFG_REBIND:
486                         enum_to_verb( yn_mode, ( ( li->li_flags & LDAP_BACK_F_SAVECRED ) == LDAP_BACK_F_SAVECRED ), &bv );
487                         if ( BER_BVISNULL( &bv ) ) {
488                                 /* there's something wrong... */
489                                 assert( 0 );
490                                 rc = 1;
491
492                         } else {
493                                 value_add_one( &c->rvalue_vals, &bv );
494                         }
495                         break;
496
497                 case LDAP_BACK_CFG_CHASE:
498                         enum_to_verb( yn_mode, ( ( li->li_flags & LDAP_BACK_F_CHASE_REFERRALS ) == LDAP_BACK_F_CHASE_REFERRALS ), &bv );
499                         if ( BER_BVISNULL( &bv ) ) {
500                                 /* there's something wrong... */
501                                 assert( 0 );
502                                 rc = 1;
503
504                         } else {
505                                 value_add_one( &c->rvalue_vals, &bv );
506                         }
507                         break;
508
509                 case LDAP_BACK_CFG_T_F:
510                         enum_to_verb( t_f_mode, ( ( li->li_flags & LDAP_BACK_F_SUPPORT_T_F_MASK ) == LDAP_BACK_F_SUPPORT_T_F_MASK ), &bv );
511                         if ( BER_BVISNULL( &bv ) ) {
512                                 /* there's something wrong... */
513                                 assert( 0 );
514                                 rc = 1;
515
516                         } else {
517                                 value_add_one( &c->rvalue_vals, &bv );
518                         }
519                         break;
520
521                 case LDAP_BACK_CFG_WHOAMI:
522                         enum_to_verb( yn_mode, ( ( li->li_flags & LDAP_BACK_F_PROXY_WHOAMI ) == LDAP_BACK_F_PROXY_WHOAMI ), &bv );
523                         if ( BER_BVISNULL( &bv ) ) {
524                                 /* there's something wrong... */
525                                 assert( 0 );
526                                 rc = 1;
527
528                         } else {
529                                 value_add_one( &c->rvalue_vals, &bv );
530                         }
531                         break;
532
533                 case LDAP_BACK_CFG_TIMEOUT:
534                         BER_BVZERO( &bv );
535
536                         slap_cf_aux_table_unparse( li->li_timeout, &bv, timeout_table );
537
538                         if ( !BER_BVISNULL( &bv ) ) {   
539                                 for ( i = 0; isspace( bv.bv_val[ i ] ); i++ )
540                                         /* count spaces */ ;
541
542                                 if ( i ) {
543                                         bv.bv_len -= i;
544                                         AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ],
545                                                 bv.bv_len + 1 );
546                                 }
547
548                                 ber_bvarray_add( &c->rvalue_vals, &bv );
549                         }
550                         break;
551
552                 default:
553                         /* FIXME: we need to handle all... */
554                         assert( 0 );
555                         break;
556                 }
557                 return rc;
558
559         } else if ( c->op == LDAP_MOD_DELETE ) {
560                 rc = 0;
561                 switch( c->type ) {
562                 case LDAP_BACK_CFG_URI:
563                         if ( li->li_uri != NULL ) {
564                                 ch_free( li->li_uri );
565                                 li->li_uri = NULL;
566
567                                 assert( li->li_bvuri != NULL );
568                                 ber_bvarray_free( li->li_bvuri );
569                                 li->li_bvuri = NULL;
570                         }
571
572                         /* better cleanup the cached connections... */
573                         /* NOTE: don't worry about locking: if we got here,
574                          * other threads are suspended. */
575                         if ( li->li_conninfo.lai_tree != NULL ) {
576                                 avl_free( li->li_conninfo.lai_tree, ldap_back_conn_free );
577                                 li->li_conninfo.lai_tree = NULL;
578                         }
579                         
580                         break;
581
582                 case LDAP_BACK_CFG_TLS:
583                         rc = 1;
584                         break;
585
586                 case LDAP_BACK_CFG_ACL_AUTHCDN:
587                 case LDAP_BACK_CFG_ACL_PASSWD:
588                 case LDAP_BACK_CFG_ACL_METHOD:
589                         /* handled by LDAP_BACK_CFG_ACL_BIND */
590                         rc = 1;
591                         break;
592
593                 case LDAP_BACK_CFG_ACL_BIND:
594                         bindconf_free( &li->li_acl );
595                         break;
596
597                 case LDAP_BACK_CFG_IDASSERT_MODE:
598                 case LDAP_BACK_CFG_IDASSERT_AUTHCDN:
599                 case LDAP_BACK_CFG_IDASSERT_PASSWD:
600                 case LDAP_BACK_CFG_IDASSERT_METHOD:
601                         /* handled by LDAP_BACK_CFG_IDASSERT_BIND */
602                         rc = 1;
603                         break;
604
605                 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM:
606                         if ( li->li_idassert_authz != NULL ) {
607                                 ber_bvarray_free( li->li_idassert_authz );
608                                 li->li_idassert_authz = NULL;
609                         }
610                         break;
611
612                 case LDAP_BACK_CFG_IDASSERT_BIND:
613                         bindconf_free( &li->li_idassert );
614                         break;
615
616                 case LDAP_BACK_CFG_REBIND:
617                 case LDAP_BACK_CFG_CHASE:
618                 case LDAP_BACK_CFG_T_F:
619                 case LDAP_BACK_CFG_WHOAMI:
620                         rc = 1;
621                         break;
622
623                 case LDAP_BACK_CFG_TIMEOUT:
624                         for ( i = 0; i < LDAP_BACK_OP_LAST; i++ ) {
625                                 li->li_timeout[ i ] = 0;
626                         }
627                         break;
628
629                 default:
630                         /* FIXME: we need to handle all... */
631                         assert( 0 );
632                         break;
633                 }
634                 return rc;
635
636         }
637
638         switch( c->type ) {
639         case LDAP_BACK_CFG_URI: {
640                 LDAPURLDesc     *tmpludp, *lud;
641                 char            **urllist = NULL;
642                 int             urlrc = LDAP_URL_SUCCESS, i;
643
644                 if ( c->argc != 2 ) {
645                         fprintf( stderr, "%s: line %d: "
646                                         "missing uri "
647                                         "in \"uri <uri>\" line\n",
648                                         c->fname, c->lineno );
649                         return 1;
650                 }
651
652                 if ( li->li_uri != NULL ) {
653                         ch_free( li->li_uri );
654                         li->li_uri = NULL;
655
656                         assert( li->li_bvuri != NULL );
657                         ber_bvarray_free( li->li_bvuri );
658                         li->li_bvuri = NULL;
659                 }
660
661                 /* PARANOID: DN and more are not required nor allowed */
662                 urlrc = ldap_url_parselist_ext( &lud, c->value_string, ", \t" );
663                 if ( urlrc != LDAP_URL_SUCCESS ) {
664                         char    *why;
665
666                         switch ( urlrc ) {
667                         case LDAP_URL_ERR_MEM:
668                                 why = "no memory";
669                                 break;
670                         case LDAP_URL_ERR_PARAM:
671                                 why = "parameter is bad";
672                                 break;
673                         case LDAP_URL_ERR_BADSCHEME:
674                                 why = "URL doesn't begin with \"[c]ldap[si]://\"";
675                                 break;
676                         case LDAP_URL_ERR_BADENCLOSURE:
677                                 why = "URL is missing trailing \">\"";
678                                 break;
679                         case LDAP_URL_ERR_BADURL:
680                                 why = "URL is bad";
681                                 break;
682                         case LDAP_URL_ERR_BADHOST:
683                                 why = "host/port is bad";
684                                 break;
685                         case LDAP_URL_ERR_BADATTRS:
686                                 why = "bad (or missing) attributes";
687                                 break;
688                         case LDAP_URL_ERR_BADSCOPE:
689                                 why = "scope string is invalid (or missing)";
690                                 break;
691                         case LDAP_URL_ERR_BADFILTER:
692                                 why = "bad or missing filter";
693                                 break;
694                         case LDAP_URL_ERR_BADEXTS:
695                                 why = "bad or missing extensions";
696                                 break;
697                         default:
698                                 why = "unknown reason";
699                                 break;
700                         }
701                         fprintf( stderr, "%s: line %d: "
702                                         "unable to parse uri \"%s\" "
703                                         "in \"uri <uri>\" line: %s\n",
704                                         c->fname, c->lineno, c->value_string, why );
705                         urlrc = 1;
706                         goto done_url;
707                 }
708
709                 for ( i = 0, tmpludp = lud;
710                                 tmpludp;
711                                 i++, tmpludp = tmpludp->lud_next )
712                 {
713                         if ( ( tmpludp->lud_dn != NULL
714                                                 && tmpludp->lud_dn[0] != '\0' )
715                                         || tmpludp->lud_attrs != NULL
716                                         /* || tmpludp->lud_scope != LDAP_SCOPE_DEFAULT */
717                                         || tmpludp->lud_filter != NULL
718                                         || tmpludp->lud_exts != NULL )
719                         {
720                                 fprintf( stderr, "%s: line %d: "
721                                                 "warning, only protocol, "
722                                                 "host and port allowed "
723                                                 "in \"uri <uri>\" statement "
724                                                 "for uri #%d of \"%s\"\n",
725                                                 c->fname, c->lineno, i, c->value_string );
726                         }
727                 }
728
729                 for ( i = 0, tmpludp = lud;
730                                 tmpludp;
731                                 i++, tmpludp = tmpludp->lud_next )
732                         /* just count */
733                         ;
734                 urllist = ch_calloc( sizeof( char * ), i + 1 );
735
736                 for ( i = 0, tmpludp = lud;
737                                 tmpludp;
738                                 i++, tmpludp = tmpludp->lud_next )
739                 {
740                         LDAPURLDesc     tmplud;
741                         ber_len_t       oldlen = 0, len;
742
743                         tmplud = *tmpludp;
744                         tmplud.lud_dn = "";
745                         tmplud.lud_attrs = NULL;
746                         tmplud.lud_filter = NULL;
747                         if ( !ldap_is_ldapi_url( tmplud.lud_scheme ) ) {
748                                 tmplud.lud_exts = NULL;
749                                 tmplud.lud_crit_exts = 0;
750                         }
751
752                         urllist[ i ]  = ldap_url_desc2str( &tmplud );
753
754                         if ( urllist[ i ] == NULL ) {
755                                 fprintf( stderr, "%s: line %d: "
756                                         "unable to rebuild uri "
757                                         "in \"uri <uri>\" statement "
758                                         "for \"%s\"\n",
759                                         c->fname, c->lineno, c->argv[ 1 ] );
760                                 urlrc = 1;
761                                 goto done_url;
762                         }
763                 }
764
765                 li->li_uri = ldap_charray2str( urllist, " " );
766                 for ( i = 0; urllist[ i ] != NULL; i++ ) {
767                         struct berval   bv;
768
769                         ber_str2bv( urllist[ i ], 0, 0, &bv );
770                         ber_bvarray_add( &li->li_bvuri, &bv );
771                         urllist[ i ] = NULL;
772                 }
773                 ldap_memfree( urllist );
774                 urllist = NULL;
775
776 done_url:;
777                 if ( urllist ) {
778                         ldap_charray_free( urllist );
779                 }
780                 if ( lud ) {
781                         ldap_free_urllist( lud );
782                 }
783                 if ( urlrc != LDAP_URL_SUCCESS ) {
784                         return 1;
785                 }
786                 break;
787         }
788
789         case LDAP_BACK_CFG_TLS:
790                 i = verb_to_mask( c->argv[1], tls_mode );
791                 if ( BER_BVISNULL( &tls_mode[i].word ) ) {
792                         return 1;
793                 }
794                 li->li_flags &= ~LDAP_BACK_F_TLS_MASK;
795                 li->li_flags |= tls_mode[i].mask;
796                 break;
797
798         case LDAP_BACK_CFG_ACL_AUTHCDN:
799                 switch ( li->li_acl_authmethod ) {
800                 case LDAP_AUTH_NONE:
801                         li->li_acl_authmethod = LDAP_AUTH_SIMPLE;
802                         break;
803
804                 case LDAP_AUTH_SIMPLE:
805                         break;
806
807                 default:
808                         fprintf( stderr, "%s: line %d: "
809                                 "\"acl-authcDN <DN>\" incompatible "
810                                 "with auth method %d.",
811                                 c->fname, c->lineno, li->li_acl_authmethod );
812                         return 1;
813                 }
814                 if ( !BER_BVISNULL( &li->li_acl_authcDN ) ) {
815                         free( li->li_acl_authcDN.bv_val );
816                 }
817                 ber_memfree_x( c->value_dn.bv_val, NULL );
818                 li->li_acl_authcDN = c->value_ndn;
819                 BER_BVZERO( &c->value_dn );
820                 BER_BVZERO( &c->value_ndn );
821                 break;
822
823         case LDAP_BACK_CFG_ACL_PASSWD:
824                 switch ( li->li_acl_authmethod ) {
825                 case LDAP_AUTH_NONE:
826                         li->li_acl_authmethod = LDAP_AUTH_SIMPLE;
827                         break;
828
829                 case LDAP_AUTH_SIMPLE:
830                         break;
831
832                 default:
833                         fprintf( stderr, "%s: line %d: "
834                                 "\"acl-passwd <cred>\" incompatible "
835                                 "with auth method %d.",
836                                 c->fname, c->lineno, li->li_acl_authmethod );
837                         return 1;
838                 }
839                 if ( !BER_BVISNULL( &li->li_acl_passwd ) ) {
840                         free( li->li_acl_passwd.bv_val );
841                 }
842                 ber_str2bv( c->argv[ 1 ], 0, 1, &li->li_acl_passwd );
843                 break;
844
845         case LDAP_BACK_CFG_ACL_METHOD:
846         case LDAP_BACK_CFG_ACL_BIND:
847                 for ( i = 1; i < c->argc; i++ ) {
848                         if ( bindconf_parse( c->argv[ i ], &li->li_acl ) ) {
849                                 return 1;
850                         }
851                 }
852                 break;
853
854         case LDAP_BACK_CFG_IDASSERT_MODE:
855                 i = verb_to_mask( c->argv[1], idassert_mode );
856                 if ( BER_BVISNULL( &idassert_mode[i].word ) ) {
857                         if ( strncasecmp( c->argv[1], "u:", STRLENOF( "u:" ) ) == 0 ) {
858                                 li->li_idassert_mode = LDAP_BACK_IDASSERT_OTHERID;
859                                 ber_str2bv( c->argv[1], 0, 1, &li->li_idassert_authzID );
860                                 li->li_idassert_authzID.bv_val[ 0 ] = 'u';
861                                 
862                         } else {
863                                 struct berval   id, ndn;
864
865                                 ber_str2bv( c->argv[1], 0, 0, &id );
866
867                                 if ( strncasecmp( c->argv[1], "dn:", STRLENOF( "dn:" ) ) == 0 ) {
868                                         id.bv_val += STRLENOF( "dn:" );
869                                         id.bv_len -= STRLENOF( "dn:" );
870                                 }
871
872                                 rc = dnNormalize( 0, NULL, NULL, &id, &ndn, NULL );
873                                 if ( rc != LDAP_SUCCESS ) {
874                                         Debug( LDAP_DEBUG_ANY,
875                                                 "%s: line %d: idassert ID \"%s\" is not a valid DN\n",
876                                                 c->fname, c->lineno, c->argv[1] );
877                                         return 1;
878                                 }
879
880                                 li->li_idassert_authzID.bv_len = STRLENOF( "dn:" ) + ndn.bv_len;
881                                 li->li_idassert_authzID.bv_val = ch_malloc( li->li_idassert_authzID.bv_len + 1 );
882                                 AC_MEMCPY( li->li_idassert_authzID.bv_val, "dn:", STRLENOF( "dn:" ) );
883                                 AC_MEMCPY( &li->li_idassert_authzID.bv_val[ STRLENOF( "dn:" ) ], ndn.bv_val, ndn.bv_len + 1 );
884                                 ch_free( ndn.bv_val );
885
886                                 li->li_idassert_mode = LDAP_BACK_IDASSERT_OTHERDN;
887                         }
888
889                 } else {
890                         li->li_idassert_mode = idassert_mode[i].mask;
891                 }
892
893                 if ( c->argc > 2 ) {
894                         int     i;
895
896                         for ( i = 2; i < c->argc; i++ ) {
897                                 if ( strcasecmp( c->argv[ i ], "override" ) == 0 ) {
898                                         li->li_idassert_flags |= LDAP_BACK_AUTH_OVERRIDE;
899
900                                 } else if ( strcasecmp( c->argv[ i ], "prescriptive" ) == 0 ) {
901                                         li->li_idassert_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
902
903                                 } else if ( strcasecmp( c->argv[ i ], "non-prescriptive" ) == 0 ) {
904                                         li->li_idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
905
906                                 } else {
907                                         Debug( LDAP_DEBUG_ANY,
908                                                 "%s: line %d: unknown flag #%d "
909                                                 "in \"idassert-mode <args> "
910                                                 "[<flags>]\" line.\n",
911                                                 c->fname, c->lineno, i - 2 );
912                                         return 1;
913                                 }
914                         }
915                 }
916                 break;
917
918         case LDAP_BACK_CFG_IDASSERT_AUTHCDN:
919                 switch ( li->li_idassert_authmethod ) {
920                 case LDAP_AUTH_NONE:
921                         li->li_idassert_authmethod = LDAP_AUTH_SIMPLE;
922                         break;
923
924                 case LDAP_AUTH_SIMPLE:
925                         break;
926
927                 default:
928                         fprintf( stderr, "%s: line %d: "
929                                 "\"idassert-authcDN <DN>\" incompatible "
930                                 "with auth method %d.",
931                                 c->fname, c->lineno, li->li_idassert_authmethod );
932                         return 1;
933                 }
934                 if ( !BER_BVISNULL( &li->li_idassert_authcDN ) ) {
935                         free( li->li_idassert_authcDN.bv_val );
936                 }
937                 ber_memfree_x( c->value_dn.bv_val, NULL );
938                 li->li_idassert_authcDN = c->value_ndn;
939                 BER_BVZERO( &c->value_dn );
940                 BER_BVZERO( &c->value_ndn );
941                 break;
942
943         case LDAP_BACK_CFG_IDASSERT_PASSWD:
944                 switch ( li->li_idassert_authmethod ) {
945                 case LDAP_AUTH_NONE:
946                         li->li_idassert_authmethod = LDAP_AUTH_SIMPLE;
947                         break;
948
949                 case LDAP_AUTH_SIMPLE:
950                         break;
951
952                 default:
953                         fprintf( stderr, "%s: line %d: "
954                                 "\"idassert-passwd <cred>\" incompatible "
955                                 "with auth method %d.",
956                                 c->fname, c->lineno, li->li_idassert_authmethod );
957                         return 1;
958                 }
959                 if ( !BER_BVISNULL( &li->li_idassert_passwd ) ) {
960                         free( li->li_idassert_passwd.bv_val );
961                 }
962                 ber_str2bv( c->argv[ 1 ], 0, 1, &li->li_idassert_passwd );
963                 break;
964
965         case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
966                 struct berval   bv;
967 #ifdef SLAP_AUTHZ_SYNTAX
968                 struct berval   in;
969                 int             rc;
970
971                 ber_str2bv( c->argv[ 1 ], 0, 0, &in );
972                 rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL );
973                 if ( rc != LDAP_SUCCESS ) {
974                         fprintf( stderr, "%s: %d: "
975                                 "\"idassert-authzFrom <authz>\": "
976                                 "invalid syntax.\n",
977                                 c->fname, c->lineno );
978                         return 1;
979                 }
980 #else /* !SLAP_AUTHZ_SYNTAX */
981                 ber_str2bv( c->argv[ 1 ], 0, 1, &bv );
982 #endif /* !SLAP_AUTHZ_SYNTAX */
983                 ber_bvarray_add( &li->li_idassert_authz, &bv );
984                 } break;
985
986         case LDAP_BACK_CFG_IDASSERT_METHOD:
987                 /* no longer supported */
988                 fprintf( stderr, "%s: %d: "
989                         "\"idassert-method <args>\": "
990                         "no longer supported; use \"idassert-bind\".\n",
991                         c->fname, c->lineno );
992                 return 1;
993
994         case LDAP_BACK_CFG_IDASSERT_BIND:
995                 for ( i = 1; i < c->argc; i++ ) {
996                         if ( strncasecmp( c->argv[ i ], "mode=", STRLENOF( "mode=" ) ) == 0 ) {
997                                 char    *argvi = c->argv[ i ] + STRLENOF( "mode=" );
998                                 int     j;
999
1000                                 j = verb_to_mask( argvi, idassert_mode );
1001                                 if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) {
1002                                         fprintf( stderr, "%s: %d: "
1003                                                 "\"idassert-bind <args>\": "
1004                                                 "unknown mode \"%s\".\n",
1005                                                 c->fname, c->lineno, argvi );
1006                                         return 1;
1007                                 }
1008
1009                                 li->li_idassert_mode = idassert_mode[ j ].mask;
1010
1011                         } else if ( strncasecmp( c->argv[ i ], "authz=", STRLENOF( "authz=" ) ) == 0 ) {
1012                                 char    *argvi = c->argv[ i ] + STRLENOF( "authz=" );
1013
1014                                 if ( strcasecmp( argvi, "native" ) == 0 ) {
1015                                         if ( li->li_idassert_authmethod != LDAP_AUTH_SASL ) {
1016                                                 fprintf( stderr, "%s: %d: "
1017                                                         "\"idassert-bind <args>\": "
1018                                                         "authz=\"native\" incompatible "
1019                                                         "with auth method.\n",
1020                                                         c->fname, c->lineno );
1021                                                 return 1;
1022                                         }
1023                                         li->li_idassert_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
1024
1025                                 } else if ( strcasecmp( argvi, "proxyAuthz" ) == 0 ) {
1026                                         li->li_idassert_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
1027
1028                                 } else {
1029                                         fprintf( stderr, "%s: %d: "
1030                                                 "\"idassert-bind <args>\": "
1031                                                 "unknown authz \"%s\".\n",
1032                                                 c->fname, c->lineno, argvi );
1033                                         return 1;
1034                                 }
1035
1036                         } else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) {
1037                                 char    *argvi = c->argv[ i ] + STRLENOF( "flags=" );
1038                                 char    **flags = ldap_str2charray( argvi, "," );
1039                                 int     j;
1040
1041                                 if ( flags == NULL ) {
1042                                         fprintf( stderr, "%s: %d: "
1043                                                 "\"idassert-bind <args>\": "
1044                                                 "unable to parse flags \"%s\".\n",
1045                                                 c->fname, c->lineno, argvi );
1046                                         return 1;
1047                                 }
1048
1049                                 for ( j = 0; flags[ j ] != NULL; j++ ) {
1050                                         if ( strcasecmp( flags[ j ], "override" ) == 0 ) {
1051                                                 li->li_idassert_flags |= LDAP_BACK_AUTH_OVERRIDE;
1052
1053                                         } else if ( strcasecmp( flags[ j ], "prescriptive" ) == 0 ) {
1054                                                 li->li_idassert_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
1055
1056                                         } else if ( strcasecmp( flags[ j ], "non-prescriptive" ) == 0 ) {
1057                                                 li->li_idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
1058
1059                                         } else {
1060                                                 fprintf( stderr, "%s: %d: "
1061                                                         "\"idassert-bind <args>\": "
1062                                                         "unknown flag \"%s\".\n",
1063                                                         c->fname, c->lineno, flags[ j ] );
1064                                                 return 1;
1065                                         }
1066                                 }
1067
1068                                 ldap_charray_free( flags );
1069
1070                         } else if ( bindconf_parse( c->argv[ i ], &li->li_idassert ) ) {
1071                                 return 1;
1072                         }
1073                 }
1074                 break;
1075
1076         case LDAP_BACK_CFG_REBIND: {
1077                 int     dorebind = 0;
1078
1079                 if ( c->argc == 1 ) {
1080                         /* legacy */
1081                         dorebind = 1;
1082
1083                 } else {
1084                         i = verb_to_mask( c->argv[1], yn_mode );
1085                         if ( BER_BVISNULL( &yn_mode[i].word ) ) {
1086                                 return 1;
1087                         }
1088                         if ( yn_mode[i].mask & LDAP_BACK_C_YES ) {
1089                                 dorebind = 1;
1090                         }
1091                 }
1092
1093                 if ( dorebind ) {
1094                         li->li_flags |= LDAP_BACK_F_SAVECRED;
1095
1096                 } else {
1097                         li->li_flags &= ~LDAP_BACK_F_SAVECRED;
1098                 }
1099                 } break;
1100
1101         case LDAP_BACK_CFG_CHASE: {
1102                 int     dochase = 0;
1103
1104                 if ( c->argc == 1 ) {
1105                         /* legacy */
1106                         dochase = 1;
1107
1108                 } else {
1109                         i = verb_to_mask( c->argv[1], yn_mode );
1110                         if ( BER_BVISNULL( &yn_mode[i].word ) ) {
1111                                 return 1;
1112                         }
1113                         if ( yn_mode[i].mask & LDAP_BACK_C_YES ) {
1114                                 dochase = 1;
1115                         }
1116                 }
1117
1118                 if ( dochase ) {
1119                         li->li_flags |= LDAP_BACK_F_CHASE_REFERRALS;
1120
1121                 } else {
1122                         li->li_flags &= ~LDAP_BACK_F_CHASE_REFERRALS;
1123                 }
1124                 } break;
1125
1126         case LDAP_BACK_CFG_T_F:
1127                 i = verb_to_mask( c->argv[1], t_f_mode );
1128                 if ( BER_BVISNULL( &t_f_mode[i].word ) ) {
1129                         return 1;
1130                 }
1131                 li->li_flags &= ~LDAP_BACK_F_SUPPORT_T_F_MASK;
1132                 li->li_flags |= t_f_mode[i].mask;
1133                 break;
1134
1135         case LDAP_BACK_CFG_WHOAMI: {
1136                 int     dowhoami = 0;
1137
1138                 if ( c->argc == 1 ) {
1139                         /* legacy */
1140                         dowhoami = 1;
1141
1142                 } else {
1143                         i = verb_to_mask( c->argv[1], yn_mode );
1144                         if ( BER_BVISNULL( &yn_mode[i].word ) ) {
1145                                 return 1;
1146                         }
1147                         if ( yn_mode[i].mask & LDAP_BACK_C_YES ) {
1148                                 dowhoami = 1;
1149                         }
1150                 }
1151
1152                 if ( dowhoami ) {
1153                         li->li_flags |= LDAP_BACK_F_PROXY_WHOAMI;
1154
1155                         load_extop( (struct berval *)&slap_EXOP_WHOAMI,
1156                                         0, ldap_back_exop_whoami );
1157
1158                 } else {
1159                         li->li_flags &= ~LDAP_BACK_F_PROXY_WHOAMI;
1160                 }
1161                 } break;
1162
1163         case LDAP_BACK_CFG_TIMEOUT:
1164                 if ( c->argc < 2 ) {
1165                         return 1;
1166                 }
1167
1168                 for ( i = 1; i < c->argc; i++ ) {
1169                         if ( isdigit( c->argv[ i ][ 0 ] ) ) {
1170                                 char            *next;
1171                                 int             j;
1172                                 unsigned        u;
1173
1174                                 u = strtoul( c->argv[ i ], &next, 0 );
1175                                 if ( next == c->argv[ i ] || next[ 0 ] != '\0' ) {
1176                                         return 1;
1177                                 }
1178
1179                                 for ( j = 0; j < LDAP_BACK_OP_LAST; j++ ) {
1180                                         li->li_timeout[ j ] = u;
1181                                 }
1182
1183                                 continue;
1184                         }
1185
1186                         if ( slap_cf_aux_table_parse( c->argv[ i ], li->li_timeout, timeout_table, "slapd-ldap timeout" ) ) {
1187                                 return 1;
1188                         }
1189                 }
1190                 break;
1191
1192         case LDAP_BACK_CFG_REWRITE:
1193                 fprintf( stderr, "%s: line %d: "
1194                         "rewrite/remap capabilities have been moved "
1195                         "to the \"rwm\" overlay; see slapo-rwm(5) "
1196                         "for details (hint: add \"overlay rwm\" "
1197                         "and prefix all directives with \"rwm-\").\n",
1198                         c->fname, c->lineno );
1199                 return 1;
1200                 
1201         default:
1202                 /* FIXME: try to catch inconsistencies */
1203                 assert( 0 );
1204                 break;
1205         }
1206
1207         return 0;
1208 }
1209
1210 int
1211 ldap_back_init_cf( BackendInfo *bi )
1212 {
1213         int                     rc;
1214         AttributeDescription    *ad = NULL;
1215         const char              *text;
1216
1217         bi->bi_cf_ocs = ldapocs;
1218
1219         rc = config_register_schema( ldapcfg, ldapocs );
1220         if ( rc ) {
1221                 return rc;
1222         }
1223
1224         /* setup olcDbAclPasswd and olcDbIDAssertPasswd 
1225          * to be base64-encoded when written in LDIF form;
1226          * basically, we don't care if it fails */
1227         rc = slap_str2ad( "olcDbACLPasswd", &ad, &text );
1228         if ( rc ) {
1229                 Debug( LDAP_DEBUG_ANY, "config_back_initialize: "
1230                         "warning, unable to get \"olcDbACLPasswd\" "
1231                         "attribute description: %d: %s\n",
1232                         rc, text, 0 );
1233         } else {
1234                 (void)ldif_must_b64_encode_register( ad->ad_cname.bv_val,
1235                         ad->ad_type->sat_oid );
1236         }
1237
1238         ad = NULL;
1239         rc = slap_str2ad( "olcDbIDAssertPasswd", &ad, &text );
1240         if ( rc ) {
1241                 Debug( LDAP_DEBUG_ANY, "config_back_initialize: "
1242                         "warning, unable to get \"olcDbIDAssertPasswd\" "
1243                         "attribute description: %d: %s\n",
1244                         rc, text, 0 );
1245         } else {
1246                 (void)ldif_must_b64_encode_register( ad->ad_cname.bv_val,
1247                         ad->ad_type->sat_oid );
1248         }
1249
1250         return 0;
1251 }
1252
1253
1254 static int
1255 ldap_back_exop_whoami(
1256                 Operation       *op,
1257                 SlapReply       *rs )
1258 {
1259         struct berval *bv = NULL;
1260
1261         if ( op->oq_extended.rs_reqdata != NULL ) {
1262                 /* no request data should be provided */
1263                 rs->sr_text = "no request data expected";
1264                 return rs->sr_err = LDAP_PROTOCOL_ERROR;
1265         }
1266
1267         Statslog( LDAP_DEBUG_STATS, "%s WHOAMI\n",
1268             op->o_log_prefix, 0, 0, 0, 0 );
1269
1270         rs->sr_err = backend_check_restrictions( op, rs, 
1271                         (struct berval *)&slap_EXOP_WHOAMI );
1272         if( rs->sr_err != LDAP_SUCCESS ) return rs->sr_err;
1273
1274         /* if auth'd by back-ldap and request is proxied, forward it */
1275         if ( op->o_conn->c_authz_backend && !strcmp(op->o_conn->c_authz_backend->be_type, "ldap" ) && !dn_match(&op->o_ndn, &op->o_conn->c_ndn)) {
1276                 ldapconn_t      *lc;
1277
1278                 LDAPControl c, *ctrls[2] = {NULL, NULL};
1279                 LDAPMessage *res;
1280                 Operation op2 = *op;
1281                 ber_int_t msgid;
1282                 int doretry = 1;
1283
1284                 ctrls[0] = &c;
1285                 op2.o_ndn = op->o_conn->c_ndn;
1286                 lc = ldap_back_getconn(&op2, rs, LDAP_BACK_SENDERR);
1287                 if (!lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR )) {
1288                         return -1;
1289                 }
1290                 c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
1291                 c.ldctl_iscritical = 1;
1292                 c.ldctl_value.bv_val = ch_malloc(op->o_ndn.bv_len+4);
1293                 c.ldctl_value.bv_len = op->o_ndn.bv_len + 3;
1294                 strcpy(c.ldctl_value.bv_val, "dn:");
1295                 strcpy(c.ldctl_value.bv_val+3, op->o_ndn.bv_val);
1296
1297 retry:
1298                 rs->sr_err = ldap_whoami(lc->lc_ld, ctrls, NULL, &msgid);
1299                 if (rs->sr_err == LDAP_SUCCESS) {
1300                         if (ldap_result(lc->lc_ld, msgid, 1, NULL, &res) == -1) {
1301                                 ldap_get_option(lc->lc_ld, LDAP_OPT_ERROR_NUMBER,
1302                                         &rs->sr_err);
1303                                 if ( rs->sr_err == LDAP_SERVER_DOWN && doretry ) {
1304                                         doretry = 0;
1305                                         if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) )
1306                                                 goto retry;
1307                                 }
1308                                 ldap_back_freeconn( op, lc, 1 );
1309                                 lc = NULL;
1310
1311                         } else {
1312                                 rs->sr_err = ldap_parse_whoami(lc->lc_ld, res, &bv);
1313                                 ldap_msgfree(res);
1314                         }
1315                 }
1316                 ch_free(c.ldctl_value.bv_val);
1317                 if (rs->sr_err != LDAP_SUCCESS) {
1318                         rs->sr_err = slap_map_api2result( rs );
1319                 }
1320
1321                 if ( lc != NULL ) {
1322                         ldap_back_release_conn( &op2, rs, lc );
1323                 }
1324
1325         } else {
1326         /* else just do the same as before */
1327                 bv = (struct berval *) ch_malloc( sizeof(struct berval) );
1328                 if ( !BER_BVISEMPTY( &op->o_dn ) ) {
1329                         bv->bv_len = op->o_dn.bv_len + STRLENOF("dn:");
1330                         bv->bv_val = ch_malloc( bv->bv_len + 1 );
1331                         AC_MEMCPY( bv->bv_val, "dn:", STRLENOF("dn:") );
1332                         AC_MEMCPY( &bv->bv_val[STRLENOF("dn:")], op->o_dn.bv_val,
1333                                 op->o_dn.bv_len );
1334                         bv->bv_val[bv->bv_len] = '\0';
1335                 } else {
1336                         bv->bv_len = 0;
1337                         bv->bv_val = NULL;
1338                 }
1339         }
1340
1341         rs->sr_rspdata = bv;
1342         return rs->sr_err;
1343 }
1344
1345