]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/config.c
note an issue
[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_REWRITE
63 };
64
65 static ConfigTable ldapcfg[] = {
66         { "uri", "uri", 2, 2, 0,
67                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_URI,
68                 ldap_back_cf_gen, "( OLcfgDbAt:0.14 "
69                         "NAME 'olcDbURI' "
70                         "DESC 'URI (list) for remote DSA' "
71                         "SYNTAX OMsDirectoryString "
72                         "SINGLE-VALUE )",
73                 NULL, NULL },
74         { "tls", "what", 2, 2, 0,
75                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_TLS,
76                 ldap_back_cf_gen, "( OLcfgDbAt:3.1 "
77                         "NAME 'olcDbStartTLS' "
78                         "DESC 'StartTLS' "
79                         "SYNTAX OMsDirectoryString "
80                         "SINGLE-VALUE )",
81                 NULL, NULL },
82         { "acl-authcDN", "DN", 2, 2, 0,
83                 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_ACL_AUTHCDN,
84                 ldap_back_cf_gen, "( OLcfgDbAt:3.2 "
85                         "NAME 'olcDbACLAuthcDn' "
86                         "DESC 'Remote ACL administrative identity' "
87                         "OBSOLETE "
88                         "SYNTAX OMsDN "
89                         "SINGLE-VALUE )",
90                 NULL, NULL },
91         /* deprecated; aliases "acl-authcDN" */
92         { "binddn", "DN", 2, 2, 0,
93                 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_ACL_AUTHCDN,
94                 ldap_back_cf_gen, NULL, NULL, NULL },
95         { "acl-passwd", "cred", 2, 2, 0,
96                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_ACL_PASSWD,
97                 ldap_back_cf_gen, "( OLcfgDbAt:3.3 "
98                         "NAME 'olcDbACLPasswd' "
99                         "DESC 'Remote ACL administrative identity credentials' "
100                         "OBSOLETE "
101                         "SYNTAX OMsDirectoryString "
102                         "SINGLE-VALUE )",
103                 NULL, NULL },
104         /* deprecated; aliases "acl-passwd" */
105         { "bindpw", "cred", 2, 2, 0,
106                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_ACL_PASSWD,
107                 ldap_back_cf_gen, NULL, NULL, NULL },
108         { "acl-bind", "args", 2, 0, 0,
109                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_ACL_BIND,
110                 ldap_back_cf_gen, "( OLcfgDbAt:3.4 "
111                         "NAME 'olcDbACLBind' "
112                         "DESC 'Remote ACL administrative identity auth bind configuration' "
113                         "SYNTAX OMsDirectoryString "
114                         "SINGLE-VALUE )",
115                 NULL, NULL },
116         /* deprecated; aliases "acl-bind" */
117         { "acl-method", "args", 2, 0, 0,
118                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_ACL_BIND,
119                 ldap_back_cf_gen, NULL, NULL, NULL },
120         { "idassert-authcDN", "DN", 2, 2, 0,
121                 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHCDN,
122                 ldap_back_cf_gen, "( OLcfgDbAt:3.5 "
123                         "NAME 'olcDbIDAssertAuthcDn' "
124                         "DESC 'Remote Identity Assertion administrative identity' "
125                         "OBSOLETE "
126                         "SYNTAX OMsDN "
127                         "SINGLE-VALUE )",
128                 NULL, NULL },
129         /* deprecated; partially aliases "idassert-authcDN" */
130         { "proxyauthzdn", "DN", 2, 2, 0,
131                 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHCDN,
132                 ldap_back_cf_gen, NULL, NULL, NULL },
133         { "idassert-passwd", "cred", 2, 2, 0,
134                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_PASSWD,
135                 ldap_back_cf_gen, "( OLcfgDbAt:3.6 "
136                         "NAME 'olcDbIDAssertPasswd' "
137                         "DESC 'Remote Identity Assertion administrative identity credentials' "
138                         "OBSOLETE "
139                         "SYNTAX OMsDirectoryString "
140                         "SINGLE-VALUE )",
141                 NULL, NULL },
142         /* deprecated; partially aliases "idassert-passwd" */
143         { "proxyauthzpw", "cred", 2, 2, 0,
144                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_PASSWD,
145                 ldap_back_cf_gen, NULL, NULL, NULL },
146         { "idassert-bind", "args", 2, 0, 0,
147                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND,
148                 ldap_back_cf_gen, "( OLcfgDbAt:3.7 "
149                         "NAME 'olcDbIDAssertBind' "
150                         "DESC 'Remote Identity Assertion administrative identity auth bind configuration' "
151                         "SYNTAX OMsDirectoryString "
152                         "SINGLE-VALUE )",
153                 NULL, NULL },
154         { "idassert-method", "args", 2, 0, 0,
155                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND,
156                 ldap_back_cf_gen, NULL, NULL, NULL },
157         { "idassert-mode", "mode>|u:<user>|[dn:]<DN", 2, 0, 0,
158                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_MODE,
159                 ldap_back_cf_gen, "( OLcfgDbAt:3.8 "
160                         "NAME 'olcDbIDAssertMode' "
161                         "DESC 'Remote Identity Assertion mode' "
162                         "OBSOLETE "
163                         "SYNTAX OMsDirectoryString "
164                         "SINGLE-VALUE)",
165                 NULL, NULL },
166         { "idassert-authzFrom", "authzRule", 2, 2, 0,
167                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHZFROM,
168                 ldap_back_cf_gen, "( OLcfgDbAt:3.9 "
169                         "NAME 'olcDbIDAssertAuthzFrom' "
170                         "DESC 'Remote Identity Assertion authz rules' "
171                         "SYNTAX OMsDirectoryString "
172                         "X-ORDERED 'VALUES' )",
173                 NULL, NULL },
174         { "rebind-as-user", "NO|yes", 1, 2, 0,
175                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_REBIND,
176                 ldap_back_cf_gen, "( OLcfgDbAt:3.10 "
177                         "NAME 'olcDbRebindAsUser' "
178                         "DESC 'Rebind as user' "
179                         "SYNTAX OMsDirectoryString "
180                         "SINGLE-VALUE )",
181                 NULL, NULL },
182         { "chase-referrals", "YES|no", 2, 2, 0,
183                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_CHASE,
184                 ldap_back_cf_gen, "( OLcfgDbAt:3.11 "
185                         "NAME 'olcDbChaseReferrals' "
186                         "DESC 'Chase referrals' "
187                         "SYNTAX OMsDirectoryString "
188                         "SINGLE-VALUE )",
189                 NULL, NULL },
190         { "t-f-support", "NO|yes|discover", 2, 2, 0,
191                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_T_F,
192                 ldap_back_cf_gen, "( OLcfgDbAt:3.12 "
193                         "NAME 'olcDbTFSupport' "
194                         "DESC 'Absolute filters support' "
195                         "SYNTAX OMsDirectoryString "
196                         "SINGLE-VALUE )",
197                 NULL, NULL },
198         { "proxy-whoami", "NO|yes", 1, 2, 0,
199                 ARG_BERVAL|ARG_MAGIC|LDAP_BACK_CFG_WHOAMI,
200                 ldap_back_cf_gen, "( OLcfgDbAt:3.13 "
201                         "NAME 'olcDbProxyWhoAmI' "
202                         "DESC 'Proxy whoAmI exop' "
203                         "SYNTAX OMsDirectoryString "
204                         "SINGLE-VALUE )",
205                 NULL, NULL },
206         { "suffixmassage", "[virtual]> <real", 2, 3, 0,
207                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
208                 ldap_back_cf_gen, NULL, NULL, NULL },
209         { "map", "attribute|objectClass> [*|<local>] *|<remote", 3, 4, 0,
210                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
211                 ldap_back_cf_gen, NULL, NULL, NULL },
212         { "rewrite", "<arglist>", 2, 4, STRLENOF( "rewrite" ),
213                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
214                 ldap_back_cf_gen, NULL, NULL, NULL },
215         { NULL, NULL, 0, 0, 0, ARG_IGNORED,
216                 NULL, NULL, NULL, NULL }
217 };
218
219 static ConfigOCs ldapocs[] = {
220         { "( OLcfgDbOc:3.1 "
221                 "NAME 'olcLDAPConfig' "
222                 "DESC 'LDAP backend configuration' "
223                 "SUP olcDatabaseConfig "
224                 "MUST olcDbURI "
225                 "MAY ( olcDbStartTLS "
226                         "$ olcDbACLAuthcDn "
227                         "$ olcDbACLPasswd "
228                         "$ olcDbACLBind "
229                         "$ olcDbIDAssertAuthcDn "
230                         "$ olcDbIDAssertPasswd "
231                         "$ olcDbIDAssertBind "
232                         "$ olcDbIDAssertMode "
233                         "$ olcDbIDAssertAuthzFrom "
234                         "$ olcDbRebindAsUser "
235                         "$ olcDbChaseReferrals "
236                         "$ olcDbTFSupport "
237                         "$ olcDbProxyWhoAmI "
238                 ") )",
239                         Cft_Database, ldapcfg},
240         { NULL, 0, NULL }
241 };
242
243 #define LDAP_BACK_C_NO                  (0x0U)
244 #define LDAP_BACK_C_YES                 (0x1U)
245 static slap_verbmasks yn_mode[] = {
246         { BER_BVC( "yes" ),             LDAP_BACK_C_YES},
247         { BER_BVC( "no" ),              LDAP_BACK_C_NO },
248         { BER_BVNULL,                   0 }
249 };
250
251 static slap_verbmasks idassert_mode[] = {
252         { BER_BVC("self"),              LDAP_BACK_IDASSERT_SELF },
253         { BER_BVC("anonymous"),         LDAP_BACK_IDASSERT_ANONYMOUS },
254         { BER_BVC("none"),              LDAP_BACK_IDASSERT_NOASSERT },
255         { BER_BVC("legacy"),            LDAP_BACK_IDASSERT_LEGACY },
256         { BER_BVNULL,                   0 }
257 };
258
259 static slap_verbmasks tls_mode[] = {
260         { BER_BVC( "propagate" ),       LDAP_BACK_F_TLS_PROPAGATE_MASK },
261         { BER_BVC( "try-propagate" ),   LDAP_BACK_F_PROPAGATE_TLS },
262         { BER_BVC( "start" ),           LDAP_BACK_F_TLS_USE_MASK },
263         { BER_BVC( "try-start" ),       LDAP_BACK_F_USE_TLS },
264         { BER_BVC( "none" ),            LDAP_BACK_C_NO },
265         { BER_BVNULL,                   0 }
266 };
267
268 static slap_verbmasks t_f_mode[] = {
269         { BER_BVC( "yes" ),             LDAP_BACK_F_SUPPORT_T_F },
270         { BER_BVC( "discover" ),        LDAP_BACK_F_SUPPORT_T_F_DISCOVER },
271         { BER_BVC( "no" ),              LDAP_BACK_C_NO },
272         { BER_BVNULL,                   0 }
273 };
274
275 static int
276 ldap_back_cf_gen( ConfigArgs *c )
277 {
278         struct ldapinfo *li = ( struct ldapinfo * )c->be->be_private;
279         int             rc;
280         int             i;
281
282         if ( c->op == SLAP_CONFIG_EMIT ) {
283                 struct berval   bv = BER_BVNULL;
284                 rc = 0;
285
286                 switch( c->type ) {
287                 case LDAP_BACK_CFG_URI:
288                         if ( li->url != NULL ) {
289                                 c->value_string = ch_strdup( li->url );
290
291                         } else {
292                                 rc = 1;
293                         }
294                         break;
295
296                 case LDAP_BACK_CFG_TLS:
297                         enum_to_verb( tls_mode, ( li->flags & LDAP_BACK_F_TLS_MASK ), &bv );
298                         if ( BER_BVISNULL( &bv ) ) {
299                                 /* there's something wrong... */
300                                 assert( 0 );
301                                 rc = 1;
302
303                         } else {
304                                 ber_dupbv( &c->value_bv, &bv );
305                         }
306                         break;
307
308                 case LDAP_BACK_CFG_ACL_AUTHCDN:
309                 case LDAP_BACK_CFG_ACL_PASSWD:
310                 case LDAP_BACK_CFG_ACL_METHOD:
311                         /* handled by LDAP_BACK_CFG_ACL_BIND */
312                         rc = 1;
313                         break;
314
315                 case LDAP_BACK_CFG_ACL_BIND: {
316                         int     i;
317
318                         bindconf_unparse( &li->acl_sb, &c->value_bv );
319
320                         for ( i = 0; isspace( c->value_bv.bv_val[ i ] ); i++ )
321                                 /* count spaces */ ;
322
323                         if ( i ) {
324                                 c->value_bv.bv_len -= i;
325                                 AC_MEMCPY( c->value_bv.bv_val, &c->value_bv.bv_val[ i ],
326                                                 c->value_bv.bv_len + 1 );
327                         }
328                         
329                         break;
330                 }
331
332                 case LDAP_BACK_CFG_IDASSERT_MODE:
333                 case LDAP_BACK_CFG_IDASSERT_AUTHCDN:
334                 case LDAP_BACK_CFG_IDASSERT_PASSWD:
335                 case LDAP_BACK_CFG_IDASSERT_METHOD:
336                         /* handled by LDAP_BACK_CFG_IDASSERT_BIND */
337                         rc = 1;
338                         break;
339
340                 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
341                         int             i;
342
343                         if ( li->idassert_authz == NULL ) {
344                                 rc = 1;
345                                 break;
346                         }
347
348                         for ( i = 0; !BER_BVISNULL( &li->idassert_authz[ i ] ); i++ )
349                         {
350                                 struct berval   bv;
351
352                                 ber_dupbv( &bv, &li->idassert_authz[ i ] );
353                                 ber_bvarray_add( &c->rvalue_vals, &bv );
354                         }
355                         break;
356                 }
357
358                 case LDAP_BACK_CFG_IDASSERT_BIND: {
359                         int             i;
360                         struct berval   bv = BER_BVNULL,
361                                         bc = BER_BVNULL;
362                         char            *ptr;
363
364                         if ( li->idassert_authmethod != LDAP_AUTH_NONE ) {
365                                 ber_len_t       len;
366
367                                 switch ( li->idassert_mode ) {
368                                 case LDAP_BACK_IDASSERT_OTHERID:
369                                 case LDAP_BACK_IDASSERT_OTHERDN:
370                                         break;
371
372                                 default: {
373                                         struct berval   mode = BER_BVNULL;
374
375                                         enum_to_verb( idassert_mode, li->idassert_mode, &mode );
376                                         if ( BER_BVISNULL( &mode ) ) {
377                                                 /* there's something wrong... */
378                                                 assert( 0 );
379                                                 rc = 1;
380         
381                                         } else {
382                                                 bv.bv_len = STRLENOF( "mode=" ) + mode.bv_len;
383                                                 bv.bv_val = ch_malloc( bv.bv_len + 1 );
384
385                                                 ptr = lutil_strcopy( bv.bv_val, "mode=" );
386                                                 ptr = lutil_strcopy( ptr, mode.bv_val );
387                                         }
388                                         break;
389                                 }
390                                 }
391
392                                 if ( li->idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) {
393                                         len = bv.bv_len + STRLENOF( "authz=native" );
394
395                                         if ( !BER_BVISEMPTY( &bv ) ) {
396                                                 len += STRLENOF( " " );
397                                         }
398
399                                         bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
400
401                                         ptr = &bv.bv_val[ bv.bv_len ];
402
403                                         if ( !BER_BVISEMPTY( &bv ) ) {
404                                                 ptr = lutil_strcopy( ptr, " " );
405                                         }
406
407                                         (void)lutil_strcopy( ptr, "authz=native" );
408                                 }
409
410                                 len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override" );
411                                 /* flags */
412                                 if ( !BER_BVISEMPTY( &bv ) ) {
413                                         len += STRLENOF( " " );
414                                 }
415
416                                 bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
417
418                                 ptr = &bv.bv_val[ bv.bv_len ];
419
420                                 if ( !BER_BVISEMPTY( &bv ) ) {
421                                         ptr = lutil_strcopy( ptr, " " );
422                                 }
423
424                                 ptr = lutil_strcopy( ptr, "flags=" );
425
426                                 if ( li->idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
427                                         ptr = lutil_strcopy( ptr, "prescriptive" );
428                                 } else {
429                                         ptr = lutil_strcopy( ptr, "non-prescriptive" );
430                                 }
431
432                                 if ( li->idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
433                                         ptr = lutil_strcopy( ptr, ",override" );
434                                 }
435
436                                 bv.bv_len = ( ptr - bv.bv_val );
437                                 /* end-of-flags */
438                         }
439
440                         bindconf_unparse( &li->idassert_sb, &bc );
441
442                         if ( !BER_BVISNULL( &bv ) ) {
443                                 c->value_bv.bv_len = bv.bv_len + bc.bv_len;
444                                 c->value_bv.bv_val = ch_realloc( bv.bv_val, c->value_bv.bv_len + 1 );
445
446                                 assert( bc.bv_val[ 0 ] == ' ' );
447
448                                 (void)lutil_strcopy( &c->value_bv.bv_val[ bv.bv_len ], bc.bv_val );
449
450                                 free( bc.bv_val );
451
452                         } else {
453                                 for ( i = 0; isspace( bc.bv_val[ i ] ); i++ )
454                                         /* count spaces */ ;
455
456                                 if ( i ) {
457                                         bc.bv_len -= i;
458                                         AC_MEMCPY( bc.bv_val, &bc.bv_val[ i ], bc.bv_len + 1 );
459                                 }
460
461                                 c->value_bv = bv;
462                         }
463                         
464                         break;
465                 }
466
467                 case LDAP_BACK_CFG_REBIND:
468                         enum_to_verb( yn_mode, ( ( li->flags & LDAP_BACK_F_SAVECRED ) == LDAP_BACK_F_SAVECRED ), &bv );
469                         if ( BER_BVISNULL( &bv ) ) {
470                                 /* there's something wrong... */
471                                 assert( 0 );
472                                 rc = 1;
473
474                         } else {
475                                 ber_dupbv( &c->value_bv, &bv );
476                         }
477                         break;
478
479                 case LDAP_BACK_CFG_CHASE:
480                         enum_to_verb( yn_mode, ( ( li->flags & LDAP_BACK_F_CHASE_REFERRALS ) == LDAP_BACK_F_CHASE_REFERRALS ), &bv );
481                         if ( BER_BVISNULL( &bv ) ) {
482                                 /* there's something wrong... */
483                                 assert( 0 );
484                                 rc = 1;
485
486                         } else {
487                                 ber_dupbv( &c->value_bv, &bv );
488                         }
489                         break;
490
491                 case LDAP_BACK_CFG_T_F:
492                         enum_to_verb( t_f_mode, ( ( li->flags & LDAP_BACK_F_SUPPORT_T_F_MASK ) == LDAP_BACK_F_SUPPORT_T_F_MASK ), &bv );
493                         if ( BER_BVISNULL( &bv ) ) {
494                                 /* there's something wrong... */
495                                 assert( 0 );
496                                 rc = 1;
497
498                         } else {
499                                 ber_dupbv( &c->value_bv, &bv );
500                         }
501                         break;
502
503                 case LDAP_BACK_CFG_WHOAMI:
504                         enum_to_verb( yn_mode, ( ( li->flags & LDAP_BACK_F_PROXY_WHOAMI ) == LDAP_BACK_F_PROXY_WHOAMI ), &bv );
505                         if ( BER_BVISNULL( &bv ) ) {
506                                 /* there's something wrong... */
507                                 assert( 0 );
508                                 rc = 1;
509
510                         } else {
511                                 ber_dupbv( &c->value_bv, &bv );
512                         }
513                         break;
514
515                 default:
516                         /* we need to handle all... */
517                         assert( 0 );
518                         break;
519                 }
520                 return rc;
521
522         } else if ( c->op == LDAP_MOD_DELETE ) {
523                 rc = 0;
524                 switch( c->type ) {
525                 case LDAP_BACK_CFG_URI:
526                         if ( li->url != NULL ) {
527                                 ch_free( li->url );
528                                 li->url = NULL;
529                         }
530
531                         if ( li->lud != NULL ) {
532                                 ldap_free_urllist( li->lud );
533                                 li->lud = NULL;
534                         }
535                         
536                         /* better cleanup the cached connections... */
537                         /* NOTE: don't worry about locking: if we got here,
538                          * other threads are suspended. */
539                         avl_free( li->conntree, ldap_back_conn_free );
540                         li->conntree = NULL;
541                         
542                         break;
543
544                 case LDAP_BACK_CFG_TLS:
545                 case LDAP_BACK_CFG_ACL_AUTHCDN:
546                 case LDAP_BACK_CFG_ACL_PASSWD:
547                 case LDAP_BACK_CFG_ACL_METHOD:
548                         /* handled by LDAP_BACK_CFG_ACL_BIND */
549                         rc = 1;
550                         break;
551
552                 case LDAP_BACK_CFG_ACL_BIND:
553                         bindconf_free( &li->acl_sb );
554                         break;
555
556                 case LDAP_BACK_CFG_IDASSERT_MODE:
557                 case LDAP_BACK_CFG_IDASSERT_AUTHCDN:
558                 case LDAP_BACK_CFG_IDASSERT_PASSWD:
559                 case LDAP_BACK_CFG_IDASSERT_METHOD:
560                         /* handled by LDAP_BACK_CFG_IDASSERT_BIND */
561                         rc = 1;
562                         break;
563
564                 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM:
565                         if ( li->idassert_authz != NULL ) {
566                                 ber_bvarray_free( li->idassert_authz );
567                                 li->idassert_authz = NULL;
568                         }
569                         break;
570
571                 case LDAP_BACK_CFG_IDASSERT_BIND:
572                         bindconf_free( &li->idassert_sb );
573                         break;
574
575                 case LDAP_BACK_CFG_REBIND:
576                 case LDAP_BACK_CFG_CHASE:
577                 case LDAP_BACK_CFG_T_F:
578                 case LDAP_BACK_CFG_WHOAMI:
579                         rc = 1;
580                         break;
581
582                 default:
583                         /* we need to handle all... */
584                         assert( 0 );
585                         break;
586                 }
587                 return rc;
588
589         }
590
591         switch( c->type ) {
592         case LDAP_BACK_CFG_URI: {
593                 LDAPURLDesc     *tmpludp;
594                 char            **urllist;
595                 int             urlrc, i;
596
597                 if ( c->argc != 2 ) {
598                         fprintf( stderr, "%s: line %d: "
599                                         "missing uri "
600                                         "in \"uri <uri>\" line\n",
601                                         c->fname, c->lineno );
602                         return 1;
603                 }
604
605                 if ( li->url != NULL ) {
606                         ch_free( li->url );
607                 }
608
609                 if ( li->lud != NULL ) {
610                         ldap_free_urllist( li->lud );
611                 }
612
613 #if 0
614                 /* PARANOID: DN and more are not required nor allowed */
615                 urlrc = ldap_url_parselist_ext( &li->lud, c->value_string, "\t" );
616 #else
617                 urlrc = ldap_url_parselist( &li->lud, c->value_string );
618 #endif
619                 if ( urlrc != LDAP_URL_SUCCESS ) {
620                         char    *why;
621
622                         switch ( urlrc ) {
623                         case LDAP_URL_ERR_MEM:
624                                 why = "no memory";
625                                 break;
626                         case LDAP_URL_ERR_PARAM:
627                                 why = "parameter is bad";
628                                 break;
629                         case LDAP_URL_ERR_BADSCHEME:
630                                 why = "URL doesn't begin with \"[c]ldap[si]://\"";
631                                 break;
632                         case LDAP_URL_ERR_BADENCLOSURE:
633                                 why = "URL is missing trailing \">\"";
634                                 break;
635                         case LDAP_URL_ERR_BADURL:
636                                 why = "URL is bad";
637                         case LDAP_URL_ERR_BADHOST:
638                                 why = "host/port is bad";
639                                 break;
640                         case LDAP_URL_ERR_BADATTRS:
641                                 why = "bad (or missing) attributes";
642                                 break;
643                         case LDAP_URL_ERR_BADSCOPE:
644                                 why = "scope string is invalid (or missing)";
645                                 break;
646                         case LDAP_URL_ERR_BADFILTER:
647                                 why = "bad or missing filter";
648                                 break;
649                         case LDAP_URL_ERR_BADEXTS:
650                                 why = "bad or missing extensions";
651                                 break;
652                         default:
653                                 why = "unknown reason";
654                                 break;
655                         }
656                         fprintf( stderr, "%s: line %d: "
657                                         "unable to parse uri \"%s\" "
658                                         "in \"uri <uri>\" line: %s\n",
659                                         c->fname, c->lineno, c->value_string, why );
660                         return 1;
661                 }
662
663                 for ( i = 0, tmpludp = li->lud;
664                                 tmpludp;
665                                 i++, tmpludp = tmpludp->lud_next )
666                 {
667                         if ( ( tmpludp->lud_dn != NULL
668                                                 && tmpludp->lud_dn[0] != '\0' )
669                                         || tmpludp->lud_attrs != NULL
670                                         /* || tmpludp->lud_scope != LDAP_SCOPE_DEFAULT */
671                                         || tmpludp->lud_filter != NULL
672                                         || tmpludp->lud_exts != NULL )
673                         {
674                                 fprintf( stderr, "%s: line %d: "
675                                                 "warning, only protocol, "
676                                                 "host and port allowed "
677                                                 "in \"uri <uri>\" statement "
678                                                 "for uri #%d of \"%s\"\n",
679                                                 c->fname, c->lineno, i, c->value_string );
680                         }
681                 }
682
683 #if 0
684                 for ( i = 0, tmpludp = li->lud;
685                                 tmpludp;
686                                 i++, tmpludp = tmpludp->lud_next )
687                         /* just count */
688                 
689                 urllist = ch_calloc( sizeof( char * ), i + 1 );
690
691                 for ( i = 0, tmpludp = li->lud;
692                                 tmpludp;
693                                 i++, tmpludp = tmpludp->lud_next )
694                 {
695                         LDAPURLDesc     tmplud;
696                         ber_len_t       oldlen = 0, len;
697
698                         tmplud = *tmpludp;
699                         tmplud.lud_dn = "";
700                         tmplud.lud_attrs = NULL;
701                         tmplud.lud_filter = NULL;
702                         if ( !ldap_is_ldapi_url( tmplud.lud_scheme ) ) {
703                                 tmplud.lud_exts = NULL;
704                                 tmplud.lud_crit_exts = 0;
705                         }
706
707                         urllist[ i ]  = ldap_url_desc2str( &tmplud );
708
709                         if ( urllist[ i ] == NULL ) {
710                                 fprintf( stderr, "%s: line %d: "
711                                         "unable to rebuild uri "
712                                         "in \"uri <uri>\" statement "
713                                         "for \"%s\"\n",
714                                         c->fname, c->lineno, argv[ 1 ] );
715                                 return 1;
716                         }
717                 }
718
719                 li->url = ldap_charray2str( urllist, " " );
720                 ldap_charray_free( urllist );
721 #else
722                 li->url = ch_strdup( c->value_string );
723 #endif
724                 break;
725         }
726
727         case LDAP_BACK_CFG_TLS:
728                 i = verb_to_mask( c->argv[1], tls_mode );
729                 if ( BER_BVISNULL( &tls_mode[i].word ) ) {
730                         return 1;
731                 }
732                 li->flags &= ~LDAP_BACK_F_TLS_MASK;
733                 li->flags |= tls_mode[i].mask;
734                 break;
735
736         case LDAP_BACK_CFG_ACL_AUTHCDN:
737                 switch ( li->acl_authmethod ) {
738                 case LDAP_AUTH_NONE:
739                         li->acl_authmethod = LDAP_AUTH_SIMPLE;
740                         break;
741
742                 case LDAP_AUTH_SIMPLE:
743                         break;
744
745                 default:
746                         fprintf( stderr, "%s: line %d: "
747                                 "\"acl-authcDN <DN>\" incompatible "
748                                 "with auth method %d.",
749                                 c->fname, c->lineno, li->acl_authmethod );
750                         return 1;
751                 }
752                 if ( !BER_BVISNULL( &li->acl_authcDN ) ) {
753                         free( li->acl_authcDN.bv_val );
754                 }
755                 li->acl_authcDN = c->value_ndn;
756                 break;
757
758         case LDAP_BACK_CFG_ACL_PASSWD:
759                 switch ( li->acl_authmethod ) {
760                 case LDAP_AUTH_NONE:
761                         li->acl_authmethod = LDAP_AUTH_SIMPLE;
762                         break;
763
764                 case LDAP_AUTH_SIMPLE:
765                         break;
766
767                 default:
768                         fprintf( stderr, "%s: line %d: "
769                                 "\"acl-passwd <cred>\" incompatible "
770                                 "with auth method %d.",
771                                 c->fname, c->lineno, li->acl_authmethod );
772                         return 1;
773                 }
774                 if ( !BER_BVISNULL( &li->acl_passwd ) ) {
775                         free( li->acl_passwd.bv_val );
776                 }
777                 li->acl_passwd = c->value_bv;
778                 break;
779
780         case LDAP_BACK_CFG_ACL_METHOD:
781         case LDAP_BACK_CFG_ACL_BIND:
782                 for ( i = 1; i < c->argc; i++ ) {
783                         if ( bindconf_parse( c->argv[ i ], &li->acl_sb ) ) {
784                                 return 1;
785                         }
786                 }
787                 break;
788
789         case LDAP_BACK_CFG_IDASSERT_MODE:
790                 i = verb_to_mask( c->argv[1], idassert_mode );
791                 if ( BER_BVISNULL( &idassert_mode[i].word ) ) {
792                         if ( strncasecmp( c->argv[1], "u:", STRLENOF( "u:" ) ) == 0 ) {
793                                 li->idassert_mode = LDAP_BACK_IDASSERT_OTHERID;
794                                 ber_str2bv( c->argv[1], 0, 1, &li->idassert_authzID );
795                                 li->idassert_authzID.bv_val[ 0 ] = 'u';
796                                 
797                         } else {
798                                 struct berval   id, ndn;
799
800                                 ber_str2bv( c->argv[1], 0, 0, &id );
801
802                                 if ( strncasecmp( c->argv[1], "dn:", STRLENOF( "dn:" ) ) == 0 ) {
803                                         id.bv_val += STRLENOF( "dn:" );
804                                         id.bv_len -= STRLENOF( "dn:" );
805                                 }
806
807                                 rc = dnNormalize( 0, NULL, NULL, &id, &ndn, NULL );
808                                 if ( rc != LDAP_SUCCESS ) {
809                                         Debug( LDAP_DEBUG_ANY,
810                                                 "%s: line %d: idassert ID \"%s\" is not a valid DN\n",
811                                                 c->fname, c->lineno, c->argv[1] );
812                                         return 1;
813                                 }
814
815                                 li->idassert_authzID.bv_len = STRLENOF( "dn:" ) + ndn.bv_len;
816                                 li->idassert_authzID.bv_val = ch_malloc( li->idassert_authzID.bv_len + 1 );
817                                 AC_MEMCPY( li->idassert_authzID.bv_val, "dn:", STRLENOF( "dn:" ) );
818                                 AC_MEMCPY( &li->idassert_authzID.bv_val[ STRLENOF( "dn:" ) ], ndn.bv_val, ndn.bv_len + 1 );
819                                 ch_free( ndn.bv_val );
820
821                                 li->idassert_mode = LDAP_BACK_IDASSERT_OTHERDN;
822                         }
823
824                 } else {
825                         li->idassert_mode = idassert_mode[i].mask;
826                 }
827
828                 if ( c->argc > 2 ) {
829                         int     i;
830
831                         for ( i = 2; i < c->argc; i++ ) {
832                                 if ( strcasecmp( c->argv[ i ], "override" ) == 0 ) {
833                                         li->idassert_flags |= LDAP_BACK_AUTH_OVERRIDE;
834
835                                 } else if ( strcasecmp( c->argv[ i ], "prescriptive" ) == 0 ) {
836                                         li->idassert_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
837
838                                 } else if ( strcasecmp( c->argv[ i ], "non-prescriptive" ) == 0 ) {
839                                         li->idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
840
841                                 } else {
842                                         Debug( LDAP_DEBUG_ANY,
843                                                 "%s: line %d: unknown flag #%d "
844                                                 "in \"idassert-mode <args> "
845                                                 "[<flags>]\" line.\n",
846                                                 c->fname, c->lineno, i - 2 );
847                                         return 1;
848                                 }
849                         }
850                 }
851                 break;
852
853         case LDAP_BACK_CFG_IDASSERT_AUTHCDN:
854                 switch ( li->idassert_authmethod ) {
855                 case LDAP_AUTH_NONE:
856                         li->idassert_authmethod = LDAP_AUTH_SIMPLE;
857                         break;
858
859                 case LDAP_AUTH_SIMPLE:
860                         break;
861
862                 default:
863                         fprintf( stderr, "%s: line %d: "
864                                 "\"idassert-authcDN <DN>\" incompatible "
865                                 "with auth method %d.",
866                                 c->fname, c->lineno, li->idassert_authmethod );
867                         return 1;
868                 }
869                 if ( !BER_BVISNULL( &li->idassert_authcDN ) ) {
870                         free( li->idassert_authcDN.bv_val );
871                 }
872                 li->idassert_authcDN = c->value_ndn;
873                 break;
874
875         case LDAP_BACK_CFG_IDASSERT_PASSWD:
876                 switch ( li->idassert_authmethod ) {
877                 case LDAP_AUTH_NONE:
878                         li->idassert_authmethod = LDAP_AUTH_SIMPLE;
879                         break;
880
881                 case LDAP_AUTH_SIMPLE:
882                         break;
883
884                 default:
885                         fprintf( stderr, "%s: line %d: "
886                                 "\"idassert-passwd <cred>\" incompatible "
887                                 "with auth method %d.",
888                                 c->fname, c->lineno, li->idassert_authmethod );
889                         return 1;
890                 }
891                 if ( !BER_BVISNULL( &li->idassert_passwd ) ) {
892                         free( li->idassert_passwd.bv_val );
893                 }
894                 li->idassert_passwd = c->value_bv;
895                 break;
896
897         case LDAP_BACK_CFG_IDASSERT_AUTHZFROM:
898                 ber_bvarray_add( &li->idassert_authz, &c->value_bv );
899                 break;
900
901         case LDAP_BACK_CFG_IDASSERT_METHOD:
902                 /* no longer supported */
903                 fprintf( stderr, "%s: %d: "
904                         "\"idassert-method <args>\": "
905                         "no longer supported; use \"idassert-bind\".\n",
906                         c->fname, c->lineno );
907                 return 1;
908
909         case LDAP_BACK_CFG_IDASSERT_BIND:
910                 for ( i = 1; i < c->argc; i++ ) {
911                         if ( strncasecmp( c->argv[ i ], "mode=", STRLENOF( "mode=" ) ) == 0 ) {
912                                 char    *argvi = c->argv[ i ] + STRLENOF( "mode=" );
913                                 int     j;
914
915                                 j = verb_to_mask( argvi, idassert_mode );
916                                 if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) {
917                                         fprintf( stderr, "%s: %d: "
918                                                 "\"idassert-bind <args>\": "
919                                                 "unknown mode \"%s\".\n",
920                                                 c->fname, c->lineno, argvi );
921                                         return 1;
922                                 }
923
924                                 li->idassert_mode = idassert_mode[ j ].mask;
925
926                         } else if ( strncasecmp( c->argv[ i ], "authz=", STRLENOF( "authz=" ) ) == 0 ) {
927                                 char    *argvi = c->argv[ i ] + STRLENOF( "authz=" );
928
929                                 if ( strcasecmp( argvi, "native" ) == 0 ) {
930                                         if ( li->idassert_authmethod != LDAP_AUTH_SASL ) {
931                                                 fprintf( stderr, "%s: %d: "
932                                                         "\"idassert-bind <args>\": "
933                                                         "authz=\"native\" incompatible "
934                                                         "with auth method.\n",
935                                                         c->fname, c->lineno );
936                                                 return 1;
937                                         }
938                                         li->idassert_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
939
940                                 } else if ( strcasecmp( argvi, "proxyAuthz" ) == 0 ) {
941                                         li->idassert_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
942
943                                 } else {
944                                         fprintf( stderr, "%s: %d: "
945                                                 "\"idassert-bind <args>\": "
946                                                 "unknown authz \"%s\".\n",
947                                                 c->fname, c->lineno, argvi );
948                                         return 1;
949                                 }
950
951                         } else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) {
952                                 char    *argvi = c->argv[ i ] + STRLENOF( "flags=" );
953                                 char    **flags = ldap_str2charray( argvi, "," );
954                                 int     j;
955
956                                 if ( flags == NULL ) {
957                                         fprintf( stderr, "%s: %d: "
958                                                 "\"idassert-bind <args>\": "
959                                                 "unable to parse flags \"%s\".\n",
960                                                 c->fname, c->lineno, argvi );
961                                         return 1;
962                                 }
963
964                                 for ( j = 0; flags[ j ] != NULL; j++ ) {
965                                         if ( strcasecmp( flags[ j ], "override" ) == 0 ) {
966                                                 li->idassert_flags |= LDAP_BACK_AUTH_OVERRIDE;
967
968                                         } else if ( strcasecmp( flags[ j ], "prescriptive" ) == 0 ) {
969                                                 li->idassert_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
970
971                                         } else if ( strcasecmp( flags[ j ], "non-prescriptive" ) == 0 ) {
972                                                 li->idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
973
974                                         } else {
975                                                 fprintf( stderr, "%s: %d: "
976                                                         "\"idassert-bind <args>\": "
977                                                         "unknown flag \"%s\".\n",
978                                                         c->fname, c->lineno, flags[ j ] );
979                                                 return 1;
980                                         }
981                                 }
982
983                                 ldap_charray_free( flags );
984
985                         } else if ( bindconf_parse( c->argv[ i ], &li->idassert_sb ) ) {
986                                 return 1;
987                         }
988                 }
989                 break;
990
991         case LDAP_BACK_CFG_REBIND: {
992                 int     dorebind = 0;
993
994                 if ( c->argc == 1 ) {
995                         /* legacy */
996                         dorebind = 1;
997
998                 } else {
999                         i = verb_to_mask( c->argv[1], yn_mode );
1000                         if ( BER_BVISNULL( &yn_mode[i].word ) ) {
1001                                 return 1;
1002                         }
1003                         if ( yn_mode[i].mask & LDAP_BACK_C_YES ) {
1004                                 dorebind = 1;
1005                         }
1006                 }
1007
1008                 if ( dorebind ) {
1009                         li->flags |= LDAP_BACK_F_SAVECRED;
1010
1011                 } else {
1012                         li->flags &= ~LDAP_BACK_F_SAVECRED;
1013                 }
1014                 break;
1015         }
1016
1017         case LDAP_BACK_CFG_CHASE: {
1018                 int     dochase = 0;
1019
1020                 if ( c->argc == 1 ) {
1021                         /* legacy */
1022                         dochase = 1;
1023
1024                 } else {
1025                         i = verb_to_mask( c->argv[1], yn_mode );
1026                         if ( BER_BVISNULL( &yn_mode[i].word ) ) {
1027                                 return 1;
1028                         }
1029                         if ( yn_mode[i].mask & LDAP_BACK_C_YES ) {
1030                                 dochase = 1;
1031                         }
1032                 }
1033
1034                 if ( dochase ) {
1035                         li->flags |= LDAP_BACK_F_CHASE_REFERRALS;
1036
1037                 } else {
1038                         li->flags &= ~LDAP_BACK_F_CHASE_REFERRALS;
1039                 }
1040                 break;
1041         }
1042
1043         case LDAP_BACK_CFG_T_F:
1044                 i = verb_to_mask( c->argv[1], t_f_mode );
1045                 if ( BER_BVISNULL( &t_f_mode[i].word ) ) {
1046                         return 1;
1047                 }
1048                 li->flags &= ~LDAP_BACK_F_SUPPORT_T_F_MASK;
1049                 li->flags |= t_f_mode[i].mask;
1050                 break;
1051
1052         case LDAP_BACK_CFG_WHOAMI: {
1053                 int     dowhoami = 0;
1054
1055                 if ( c->argc == 1 ) {
1056                         /* legacy */
1057                         dowhoami = 1;
1058
1059                 } else {
1060                         i = verb_to_mask( c->argv[1], yn_mode );
1061                         if ( BER_BVISNULL( &yn_mode[i].word ) ) {
1062                                 return 1;
1063                         }
1064                         if ( yn_mode[i].mask & LDAP_BACK_C_YES ) {
1065                                 dowhoami = 1;
1066                         }
1067                 }
1068
1069                 if ( dowhoami ) {
1070                         li->flags |= LDAP_BACK_F_PROXY_WHOAMI;
1071
1072                         load_extop( (struct berval *)&slap_EXOP_WHOAMI,
1073                                         0, ldap_back_exop_whoami );
1074
1075                 } else {
1076                         li->flags &= ~LDAP_BACK_F_PROXY_WHOAMI;
1077                 }
1078                 break;
1079         }
1080
1081         case LDAP_BACK_CFG_REWRITE:
1082                 fprintf( stderr, "%s: line %d: "
1083                         "rewrite/remap capabilities have been moved "
1084                         "to the \"rwm\" overlay; see slapo-rwm(5) "
1085                         "for details (hint: add \"overlay rwm\" "
1086                         "and prefix all directives with \"rwm-\").\n",
1087                         c->fname, c->lineno );
1088                 return 1;
1089                 
1090         default:
1091                 assert( 0 );
1092         }
1093
1094         return 0;
1095 }
1096
1097 int
1098 ldap_back_init_cf( BackendInfo *bi )
1099 {
1100         int                     rc;
1101         AttributeDescription    *ad = NULL;
1102         const char              *text;
1103
1104         bi->bi_cf_ocs = ldapocs;
1105
1106         rc = config_register_schema( ldapcfg, ldapocs );
1107         if ( rc ) {
1108                 return rc;
1109         }
1110
1111         /* setup olcDbAclPasswd and olcDbIDAssertPasswd 
1112          * to be base64-encoded when written in LDIF form;
1113          * basically, we don't care if it fails */
1114         rc = slap_str2ad( "olcDbACLPasswd", &ad, &text );
1115         if ( rc ) {
1116                 Debug( LDAP_DEBUG_ANY, "config_back_initialize: "
1117                         "warning, unable to get \"olcDbACLPasswd\" "
1118                         "attribute description: %d: %s\n",
1119                         rc, text, 0 );
1120         } else {
1121                 (void)ldif_must_b64_encode_register( ad->ad_cname.bv_val,
1122                         ad->ad_type->sat_oid );
1123         }
1124
1125         ad = NULL;
1126         rc = slap_str2ad( "olcDbIDAssertPasswd", &ad, &text );
1127         if ( rc ) {
1128                 Debug( LDAP_DEBUG_ANY, "config_back_initialize: "
1129                         "warning, unable to get \"olcDbIDAssertPasswd\" "
1130                         "attribute description: %d: %s\n",
1131                         rc, text, 0 );
1132         } else {
1133                 (void)ldif_must_b64_encode_register( ad->ad_cname.bv_val,
1134                         ad->ad_type->sat_oid );
1135         }
1136
1137         return 0;
1138 }
1139
1140
1141 static int
1142 parse_idassert( BackendDB *be, const char *fname, int lineno,
1143                 int argc, char **argv );
1144
1145 static int
1146 parse_acl_auth( BackendDB *be, const char *fname, int lineno,
1147                 int argc, char **argv );
1148
1149 int
1150 ldap_back_db_config(
1151                 BackendDB       *be,
1152                 const char      *fname,
1153                 int             lineno,
1154                 int             argc,
1155                 char            **argv )
1156 {
1157         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
1158
1159         if ( li == NULL ) {
1160                 fprintf( stderr, "%s: line %d: ldap backend info is null!\n",
1161                                 fname, lineno );
1162                 return 1;
1163         }
1164
1165         /* server address to query (no longer supported, use "uri" directive) */
1166         if ( strcasecmp( argv[0], "server" ) == 0 ) {
1167                 fprintf( stderr,
1168         "%s: line %d: \"server <address>\" directive is no longer supported.\n",
1169                                         fname, lineno );
1170                 return 1;
1171
1172         /* URI of server to query (obsoletes "server" directive) */
1173         } else if ( strcasecmp( argv[0], "uri" ) == 0 ) {
1174                 LDAPURLDesc     *tmpludp;
1175                 char            **urllist;
1176                 int             urlrc, i;
1177
1178                 if ( argc != 2 ) {
1179                         fprintf( stderr, "%s: line %d: "
1180                                         "missing uri "
1181                                         "in \"uri <uri>\" line\n",
1182                                         fname, lineno );
1183                         return 1;
1184                 }
1185                 if ( li->url != NULL ) {
1186                         ch_free( li->url );
1187                 }
1188                 if ( li->lud != NULL ) {
1189                         ldap_free_urllist( li->lud );
1190                 }
1191
1192 #if 0
1193                 /* PARANOID: DN and more are not required nor allowed */
1194                 urlrc = ldap_url_parselist_ext( &li->lud, argv[ 1 ], "\t" );
1195 #else
1196                 urlrc = ldap_url_parselist( &li->lud, argv[ 1 ] );
1197 #endif
1198                 if ( urlrc != LDAP_URL_SUCCESS ) {
1199                         char    *why;
1200
1201                         switch ( urlrc ) {
1202                         case LDAP_URL_ERR_MEM:
1203                                 why = "no memory";
1204                                 break;
1205                         case LDAP_URL_ERR_PARAM:
1206                                 why = "parameter is bad";
1207                                 break;
1208                         case LDAP_URL_ERR_BADSCHEME:
1209                                 why = "URL doesn't begin with \"[c]ldap[si]://\"";
1210                                 break;
1211                         case LDAP_URL_ERR_BADENCLOSURE:
1212                                 why = "URL is missing trailing \">\"";
1213                                 break;
1214                         case LDAP_URL_ERR_BADURL:
1215                                 why = "URL is bad";
1216                         case LDAP_URL_ERR_BADHOST:
1217                                 why = "host/port is bad";
1218                                 break;
1219                         case LDAP_URL_ERR_BADATTRS:
1220                                 why = "bad (or missing) attributes";
1221                                 break;
1222                         case LDAP_URL_ERR_BADSCOPE:
1223                                 why = "scope string is invalid (or missing)";
1224                                 break;
1225                         case LDAP_URL_ERR_BADFILTER:
1226                                 why = "bad or missing filter";
1227                                 break;
1228                         case LDAP_URL_ERR_BADEXTS:
1229                                 why = "bad or missing extensions";
1230                                 break;
1231                         default:
1232                                 why = "unknown reason";
1233                                 break;
1234                         }
1235                         fprintf( stderr, "%s: line %d: "
1236                                         "unable to parse uri \"%s\" "
1237                                         "in \"uri <uri>\" line: %s\n",
1238                                         fname, lineno, argv[ 1 ], why );
1239                         return 1;
1240                 }
1241
1242                 for ( i = 0, tmpludp = li->lud;
1243                                 tmpludp;
1244                                 i++, tmpludp = tmpludp->lud_next )
1245                 {
1246                         if ( ( tmpludp->lud_dn != NULL
1247                                                 && tmpludp->lud_dn[0] != '\0' )
1248                                         || tmpludp->lud_attrs != NULL
1249                                         /* || tmpludp->lud_scope != LDAP_SCOPE_DEFAULT */
1250                                         || tmpludp->lud_filter != NULL
1251                                         || tmpludp->lud_exts != NULL )
1252                         {
1253                                 fprintf( stderr, "%s: line %d: "
1254                                                 "warning, only protocol, "
1255                                                 "host and port allowed "
1256                                                 "in \"uri <uri>\" statement "
1257                                                 "for uri #%d of \"%s\"\n",
1258                                                 fname, lineno, i, argv[1] );
1259                         }
1260                 }
1261
1262 #if 0
1263                 for ( i = 0, tmpludp = li->lud;
1264                                 tmpludp;
1265                                 i++, tmpludp = tmpludp->lud_next )
1266                         /* just count */
1267                 
1268                 urllist = ch_calloc( sizeof( char * ), i + 1 );
1269
1270                 for ( i = 0, tmpludp = li->lud;
1271                                 tmpludp;
1272                                 i++, tmpludp = tmpludp->lud_next )
1273                 {
1274                         LDAPURLDesc     tmplud;
1275                         ber_len_t       oldlen = 0, len;
1276
1277                         tmplud = *tmpludp;
1278                         tmplud.lud_dn = "";
1279                         tmplud.lud_attrs = NULL;
1280                         tmplud.lud_filter = NULL;
1281                         if ( !ldap_is_ldapi_url( tmplud.lud_scheme ) ) {
1282                                 tmplud.lud_exts = NULL;
1283                                 tmplud.lud_crit_exts = 0;
1284                         }
1285
1286                         urllist[ i ]  = ldap_url_desc2str( &tmplud );
1287
1288                         if ( urllist[ i ] == NULL ) {
1289                                 fprintf( stderr, "%s: line %d: "
1290                                         "unable to rebuild uri "
1291                                         "in \"uri <uri>\" statement "
1292                                         "for \"%s\"\n",
1293                                         fname, lineno, argv[ 1 ] );
1294                                 return 1;
1295                         }
1296                 }
1297
1298                 li->url = ldap_charray2str( urllist, " " );
1299                 ldap_charray_free( urllist );
1300 #else
1301                 li->url = ch_strdup( argv[ 1 ] );
1302 #endif
1303
1304         } else if ( strcasecmp( argv[0], "tls" ) == 0 ) {
1305                 if ( argc != 2 ) {
1306                         fprintf( stderr,
1307                 "%s: line %d: \"tls <what>\" needs 1 argument.\n",
1308                                         fname, lineno );
1309                         return( 1 );
1310                 }
1311
1312                 /* none */
1313                 if ( strcasecmp( argv[1], "none" ) == 0 ) {
1314                         li->flags &= ~LDAP_BACK_F_TLS_MASK;
1315         
1316                 /* try start tls */
1317                 } else if ( strcasecmp( argv[1], "start" ) == 0 ) {
1318                         li->flags |= LDAP_BACK_F_TLS_USE_MASK;
1319         
1320                 /* try start tls */
1321                 } else if ( strcasecmp( argv[1], "try-start" ) == 0 ) {
1322                         li->flags &= ~LDAP_BACK_F_TLS_CRITICAL;
1323                         li->flags |= LDAP_BACK_F_USE_TLS;
1324         
1325                 /* propagate start tls */
1326                 } else if ( strcasecmp( argv[1], "propagate" ) == 0 ) {
1327                         li->flags |= LDAP_BACK_F_TLS_PROPAGATE_MASK;
1328                 
1329                 /* try start tls */
1330                 } else if ( strcasecmp( argv[1], "try-propagate" ) == 0 ) {
1331                         li->flags &= ~LDAP_BACK_F_TLS_CRITICAL;
1332                         li->flags |= LDAP_BACK_F_PROPAGATE_TLS;
1333
1334                 } else {
1335                         fprintf( stderr,
1336                 "%s: line %d: \"tls <what>\": unknown argument \"%s\".\n",
1337                                         fname, lineno, argv[1] );
1338                         return( 1 );
1339                 }
1340         
1341         /* remote ACL stuff... */
1342         } else if ( strncasecmp( argv[0], "acl-", STRLENOF( "acl-" ) ) == 0
1343                         || strncasecmp( argv[0], "bind", STRLENOF( "bind" ) ) == 0 )
1344         {
1345                 /* NOTE: "bind{DN,pw}" was initially used; it's now
1346                  * deprected and undocumented, it can be dropped at some
1347                  * point, since nobody should be really using it */
1348                 return parse_acl_auth( be, fname, lineno, argc, argv );
1349
1350         /* identity assertion stuff... */
1351         } else if ( strncasecmp( argv[0], "idassert-", STRLENOF( "idassert-" ) ) == 0
1352                         || strncasecmp( argv[0], "proxyauthz", STRLENOF( "proxyauthz" ) ) == 0 )
1353         {
1354                 /* NOTE: "proxyauthz{DN,pw}" was initially used; it's now
1355                  * deprected and undocumented, it can be dropped at some
1356                  * point, since nobody should be really using it */
1357                 return parse_idassert( be, fname, lineno, argc, argv );
1358
1359         /* save bind creds for referral rebinds? */
1360         } else if ( strcasecmp( argv[0], "rebind-as-user" ) == 0 ) {
1361                 switch ( argc ) {
1362                 case 1:
1363                         fprintf( stderr,
1364         "%s: line %d: \"rebind-as-user {NO|yes}\": use without args is deprecated.\n",
1365                                 fname, lineno );
1366         
1367                         li->flags |= LDAP_BACK_F_SAVECRED;
1368                         break;
1369
1370                 case 2:
1371                         if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
1372                                 li->flags |= LDAP_BACK_F_SAVECRED;
1373
1374                         } else if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
1375                                 li->flags &= ~LDAP_BACK_F_SAVECRED;
1376
1377                         } else {
1378                                 fprintf( stderr,
1379         "%s: line %d: \"rebind-as-user {NO|yes}\": unknown argument \"%s\".\n",
1380                                         fname, lineno, argv[ 1 ] );
1381                                 return( 1 );
1382                         }
1383                         break;
1384
1385                 default:
1386                         fprintf( stderr,
1387         "%s: line %d: \"rebind-as-user {NO|yes}\" needs 1 argument.\n",
1388                                         fname, lineno );
1389                         return( 1 );
1390                 }
1391
1392         } else if ( strcasecmp( argv[0], "chase-referrals" ) == 0 ) {
1393                 if ( argc != 2 ) {
1394                         fprintf( stderr,
1395         "%s: line %d: \"chase-referrals {YES|no}\" needs 1 argument.\n",
1396                                         fname, lineno );
1397                         return( 1 );
1398                 }
1399
1400                 /* this is the default; we add it because the default might change... */
1401                 if ( strcasecmp( argv[1], "yes" ) == 0 ) {
1402                         li->flags |= LDAP_BACK_F_CHASE_REFERRALS;
1403
1404                 } else if ( strcasecmp( argv[1], "no" ) == 0 ) {
1405                         li->flags &= ~LDAP_BACK_F_CHASE_REFERRALS;
1406
1407                 } else {
1408                         fprintf( stderr,
1409                 "%s: line %d: \"chase-referrals {YES|no}\": unknown argument \"%s\".\n",
1410                                         fname, lineno, argv[1] );
1411                         return( 1 );
1412                 }
1413         
1414         } else if ( strcasecmp( argv[ 0 ], "t-f-support" ) == 0 ) {
1415                 if ( argc != 2 ) {
1416                         fprintf( stderr,
1417                 "%s: line %d: \"t-f-support {NO|yes|discover}\" needs 1 argument.\n",
1418                                         fname, lineno );
1419                         return( 1 );
1420                 }
1421
1422                 if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
1423                         li->flags &= ~(LDAP_BACK_F_SUPPORT_T_F|LDAP_BACK_F_SUPPORT_T_F_DISCOVER);
1424
1425                 } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
1426                         li->flags |= LDAP_BACK_F_SUPPORT_T_F;
1427
1428                 } else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
1429                         li->flags |= LDAP_BACK_F_SUPPORT_T_F_DISCOVER;
1430
1431                 } else {
1432                         fprintf( stderr,
1433         "%s: line %d: \"t-f-support {NO|yes|discover}\": unknown argument \"%s\".\n",
1434                                 fname, lineno, argv[ 1 ] );
1435                         return 1;
1436                 }
1437
1438         /* intercept exop_who_am_i? */
1439         } else if ( strcasecmp( argv[0], "proxy-whoami" ) == 0 ) {
1440                 int     doload_extop = 0;
1441
1442                 switch ( argc ) {
1443                 case 1:
1444                         fprintf( stderr,
1445         "%s: line %d: \"proxy-whoami {NO|yes}\": use without args is deprecated.\n",
1446                                 fname, lineno );
1447         
1448                         doload_extop = 1;
1449                         break;
1450
1451                 case 2:
1452                         if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
1453                                 doload_extop = 1;
1454
1455                         } else if ( strcasecmp( argv[ 1 ], "no" ) != 0 ) {
1456                                 fprintf( stderr,
1457         "%s: line %d: \"proxy-whoami {NO|yes}\": unknown argument \"%s\".\n",
1458                                         fname, lineno, argv[ 1 ] );
1459                                 return( 1 );
1460                         }
1461                         break;
1462
1463                 default:
1464                         fprintf( stderr,
1465         "%s: line %d: \"proxy-whoami {NO|yes}\" needs 1 argument.\n",
1466                                         fname, lineno );
1467                         return( 1 );
1468                 }
1469
1470                 if ( doload_extop ) {
1471                         li->flags |= LDAP_BACK_F_PROXY_WHOAMI;
1472
1473                         load_extop( (struct berval *)&slap_EXOP_WHOAMI,
1474                                         0, ldap_back_exop_whoami );
1475                 }
1476
1477         /* FIXME: legacy: intercept old rewrite/remap directives
1478          * and try to start the rwm overlay */
1479         } else if ( strcasecmp( argv[0], "suffixmassage" ) == 0
1480                         || strcasecmp( argv[0], "map" ) == 0
1481                         || strncasecmp( argv[0], "rewrite", STRLENOF( "rewrite" ) ) == 0 )
1482         {
1483 #if 0
1484                 fprintf( stderr, "%s: line %d: "
1485                         "rewrite/remap capabilities have been moved "
1486                         "to the \"rwm\" overlay; see slapo-rwm(5) "
1487                         "for details.  I'm trying to do my best "
1488                         "to preserve backwards compatibility...\n",
1489                         fname, lineno );
1490
1491                 if ( li->rwm_started == 0 ) {
1492                         if ( overlay_config( be, "rwm" ) ) {
1493                                 fprintf( stderr, "%s: line %d: "
1494                                         "unable to configure the \"rwm\" "
1495                                         "overlay, required by directive "
1496                                         "\"%s\".\n",
1497                                         fname, lineno, argv[0] );
1498 #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
1499                                 fprintf( stderr, "\thint: try loading the \"rwm.la\" dynamic module.\n" );
1500 #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
1501                                 return( 1 );
1502                         }
1503
1504                         fprintf( stderr, "%s: line %d: back-ldap: "
1505                                 "automatically starting \"rwm\" overlay, "
1506                                 "triggered by \"%s\" directive.\n",
1507                                 fname, lineno, argv[ 0 ] );
1508
1509                 /* this is the default; we add it because the default might change... */
1510                         li->rwm_started = 1;
1511
1512                         return ( *be->bd_info->bi_db_config )( be, fname, lineno, argc, argv );
1513                 }
1514 #else
1515                 fprintf( stderr, "%s: line %d: "
1516                         "rewrite/remap capabilities have been moved "
1517                         "to the \"rwm\" overlay; see slapo-rwm(5) "
1518                         "for details (hint: add \"overlay rwm\" "
1519                         "and prefix all directives with \"rwm-\").\n",
1520                         fname, lineno );
1521 #endif
1522
1523                 return 1;
1524         
1525         /* anything else */
1526         } else {
1527                 return SLAP_CONF_UNKNOWN;
1528         }
1529
1530         return 0;
1531 }
1532
1533 static int
1534 ldap_back_exop_whoami(
1535                 Operation       *op,
1536                 SlapReply       *rs )
1537 {
1538         struct berval *bv = NULL;
1539
1540         if ( op->oq_extended.rs_reqdata != NULL ) {
1541                 /* no request data should be provided */
1542                 rs->sr_text = "no request data expected";
1543                 return rs->sr_err = LDAP_PROTOCOL_ERROR;
1544         }
1545
1546         rs->sr_err = backend_check_restrictions( op, rs, 
1547                         (struct berval *)&slap_EXOP_WHOAMI );
1548         if( rs->sr_err != LDAP_SUCCESS ) return rs->sr_err;
1549
1550         /* if auth'd by back-ldap and request is proxied, forward it */
1551         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)) {
1552                 struct ldapconn *lc;
1553
1554                 LDAPControl c, *ctrls[2] = {NULL, NULL};
1555                 LDAPMessage *res;
1556                 Operation op2 = *op;
1557                 ber_int_t msgid;
1558                 int doretry = 1;
1559
1560                 ctrls[0] = &c;
1561                 op2.o_ndn = op->o_conn->c_ndn;
1562                 lc = ldap_back_getconn(&op2, rs, LDAP_BACK_SENDERR);
1563                 if (!lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR )) {
1564                         return -1;
1565                 }
1566                 c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
1567                 c.ldctl_iscritical = 1;
1568                 c.ldctl_value.bv_val = ch_malloc(op->o_ndn.bv_len+4);
1569                 c.ldctl_value.bv_len = op->o_ndn.bv_len + 3;
1570                 strcpy(c.ldctl_value.bv_val, "dn:");
1571                 strcpy(c.ldctl_value.bv_val+3, op->o_ndn.bv_val);
1572
1573 retry:
1574                 rs->sr_err = ldap_whoami(lc->lc_ld, ctrls, NULL, &msgid);
1575                 if (rs->sr_err == LDAP_SUCCESS) {
1576                         if (ldap_result(lc->lc_ld, msgid, 1, NULL, &res) == -1) {
1577                                 ldap_get_option(lc->lc_ld, LDAP_OPT_ERROR_NUMBER,
1578                                         &rs->sr_err);
1579                                 if ( rs->sr_err == LDAP_SERVER_DOWN && doretry ) {
1580                                         doretry = 0;
1581                                         if ( ldap_back_retry( lc, op, rs, LDAP_BACK_SENDERR ) )
1582                                                 goto retry;
1583                                 }
1584                                 ldap_back_freeconn( op, lc );
1585                                 lc = NULL;
1586
1587                         } else {
1588                                 rs->sr_err = ldap_parse_whoami(lc->lc_ld, res, &bv);
1589                                 ldap_msgfree(res);
1590                         }
1591                 }
1592                 ch_free(c.ldctl_value.bv_val);
1593                 if (rs->sr_err != LDAP_SUCCESS) {
1594                         rs->sr_err = slap_map_api2result( rs );
1595                 }
1596
1597                 if ( lc != NULL ) {
1598                         ldap_back_release_conn( &op2, rs, lc );
1599                 }
1600
1601         } else {
1602         /* else just do the same as before */
1603                 bv = (struct berval *) ch_malloc( sizeof(struct berval) );
1604                 if ( !BER_BVISEMPTY( &op->o_dn ) ) {
1605                         bv->bv_len = op->o_dn.bv_len + sizeof("dn:") - 1;
1606                         bv->bv_val = ch_malloc( bv->bv_len + 1 );
1607                         AC_MEMCPY( bv->bv_val, "dn:", sizeof("dn:") - 1 );
1608                         AC_MEMCPY( &bv->bv_val[sizeof("dn:") - 1], op->o_dn.bv_val,
1609                                 op->o_dn.bv_len );
1610                         bv->bv_val[bv->bv_len] = '\0';
1611                 } else {
1612                         bv->bv_len = 0;
1613                         bv->bv_val = NULL;
1614                 }
1615         }
1616
1617         rs->sr_rspdata = bv;
1618         return rs->sr_err;
1619 }
1620
1621
1622 static int
1623 parse_idassert(
1624     BackendDB   *be,
1625     const char  *fname,
1626     int         lineno,
1627     int         argc,
1628     char        **argv
1629 )
1630 {
1631         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
1632
1633         /* identity assertion mode */
1634         if ( strcasecmp( argv[0], "idassert-mode" ) == 0 ) {
1635                 if ( argc < 2 ) {
1636                         Debug( LDAP_DEBUG_ANY,
1637                                 "%s: line %d: illegal args number %d in \"idassert-mode <args> [<flag> [...]]\" line.\n",
1638                                 fname, lineno, argc );
1639                         return 1;
1640                 }
1641
1642                 if ( strcasecmp( argv[1], "legacy" ) == 0 ) {
1643                         /* will proxyAuthz as client's identity only if bound */
1644                         li->idassert_mode = LDAP_BACK_IDASSERT_LEGACY;
1645
1646                 } else if ( strcasecmp( argv[1], "self" ) == 0 ) {
1647                         /* will proxyAuthz as client's identity */
1648                         li->idassert_mode = LDAP_BACK_IDASSERT_SELF;
1649
1650                 } else if ( strcasecmp( argv[1], "anonymous" ) == 0 ) {
1651                         /* will proxyAuthz as anonymous */
1652                         li->idassert_mode = LDAP_BACK_IDASSERT_ANONYMOUS;
1653
1654                 } else if ( strcasecmp( argv[1], "none" ) == 0 ) {
1655                         /* will not proxyAuthz */
1656                         li->idassert_mode = LDAP_BACK_IDASSERT_NOASSERT;
1657
1658                 } else {
1659                         struct berval   id;
1660                         int             rc;
1661
1662                         /* will proxyAuthz as argv[1] */
1663                         ber_str2bv( argv[1], 0, 0, &id );
1664
1665                         if ( strncasecmp( id.bv_val, "u:", STRLENOF( "u:" ) ) == 0 ) {
1666                                 /* force lowercase... */
1667                                 id.bv_val[0] = 'u';
1668                                 li->idassert_mode = LDAP_BACK_IDASSERT_OTHERID;
1669                                 ber_dupbv( &li->idassert_authzID, &id );
1670
1671                         } else {
1672                                 struct berval   dn;
1673
1674                                 /* default is DN? */
1675                                 if ( strncasecmp( id.bv_val, "dn:", STRLENOF( "dn:" ) ) == 0 ) {
1676                                         id.bv_val += STRLENOF( "dn:" );
1677                                         id.bv_len -= STRLENOF( "dn:" );
1678                                 }
1679
1680                                 rc = dnNormalize( 0, NULL, NULL, &id, &dn, NULL );
1681                                 if ( rc != LDAP_SUCCESS ) {
1682                                         Debug( LDAP_DEBUG_ANY,
1683                                                 "%s: line %d: idassert ID \"%s\" is not a valid DN\n",
1684                                                 fname, lineno, argv[1] );
1685                                         return 1;
1686                                 }
1687
1688                                 li->idassert_authzID.bv_len = STRLENOF( "dn:" ) + dn.bv_len;
1689                                 li->idassert_authzID.bv_val = ch_malloc( li->idassert_authzID.bv_len + 1 );
1690                                 AC_MEMCPY( li->idassert_authzID.bv_val, "dn:", STRLENOF( "dn:" ) );
1691                                 AC_MEMCPY( &li->idassert_authzID.bv_val[ STRLENOF( "dn:" ) ], dn.bv_val, dn.bv_len + 1 );
1692                                 ch_free( dn.bv_val );
1693
1694                                 li->idassert_mode = LDAP_BACK_IDASSERT_OTHERDN;
1695                         }
1696                 }
1697
1698                 for ( argc -= 2, argv += 2; argc--; argv++ ) {
1699                         if ( strcasecmp( argv[0], "override" ) == 0 ) {
1700                                 li->idassert_flags |= LDAP_BACK_AUTH_OVERRIDE;
1701
1702                         } else {
1703                                 Debug( LDAP_DEBUG_ANY,
1704                                         "%s: line %d: unknown flag \"%s\" "
1705                                         "in \"idassert-mode <args> "
1706                                         "[<flags>]\" line.\n",
1707                                         fname, lineno, argv[0] );
1708                                 return 1;
1709                         }
1710                 }
1711
1712         /* name to use for proxyAuthz propagation */
1713         } else if ( strcasecmp( argv[0], "idassert-authcdn" ) == 0
1714                         || strcasecmp( argv[0], "proxyauthzdn" ) == 0 )
1715         {
1716                 struct berval   dn;
1717                 int             rc;
1718
1719                 /* FIXME: "proxyauthzdn" is no longer documented, and
1720                  * temporarily supported for backwards compatibility */
1721
1722                 if ( argc != 2 ) {
1723                         fprintf( stderr,
1724         "%s: line %d: missing name in \"%s <name>\" line\n",
1725                             fname, lineno, argv[0] );
1726                         return( 1 );
1727                 }
1728
1729                 if ( !BER_BVISNULL( &li->idassert_authcDN ) ) {
1730                         fprintf( stderr, "%s: line %d: "
1731                                         "authcDN already defined; replacing...\n",
1732                                         fname, lineno );
1733                         ch_free( li->idassert_authcDN.bv_val );
1734                 }
1735                 
1736                 ber_str2bv( argv[1], 0, 0, &dn );
1737                 rc = dnNormalize( 0, NULL, NULL, &dn, &li->idassert_authcDN, NULL );
1738                 if ( rc != LDAP_SUCCESS ) {
1739                         Debug( LDAP_DEBUG_ANY,
1740                                 "%s: line %d: idassert ID \"%s\" is not a valid DN\n",
1741                                 fname, lineno, argv[1] );
1742                         return 1;
1743                 }
1744
1745         /* password to use for proxyAuthz propagation */
1746         } else if ( strcasecmp( argv[0], "idassert-passwd" ) == 0
1747                         || strcasecmp( argv[0], "proxyauthzpw" ) == 0 )
1748         {
1749                 /* FIXME: "proxyauthzpw" is no longer documented, and
1750                  * temporarily supported for backwards compatibility */
1751
1752                 if ( argc != 2 ) {
1753                         fprintf( stderr,
1754         "%s: line %d: missing password in \"%s <password>\" line\n",
1755                             fname, lineno, argv[0] );
1756                         return( 1 );
1757                 }
1758
1759                 if ( !BER_BVISNULL( &li->idassert_passwd ) ) {
1760                         fprintf( stderr, "%s: line %d: "
1761                                         "passwd already defined; replacing...\n",
1762                                         fname, lineno );
1763                         ch_free( li->idassert_passwd.bv_val );
1764                 }
1765                 
1766                 ber_str2bv( argv[1], 0, 1, &li->idassert_passwd );
1767
1768         /* rules to accept identity assertion... */
1769         } else if ( strcasecmp( argv[0], "idassert-authzFrom" ) == 0 ) {
1770                 struct berval   rule;
1771
1772                 ber_str2bv( argv[1], 0, 1, &rule );
1773
1774                 ber_bvarray_add( &li->idassert_authz, &rule );
1775
1776         } else if ( strcasecmp( argv[0], "idassert-method" ) == 0 ) {
1777                 char    *argv1;
1778
1779                 if ( argc < 2 ) {
1780                         fprintf( stderr,
1781         "%s: line %d: missing method in \"%s <method>\" line\n",
1782                             fname, lineno, argv[0] );
1783                         return( 1 );
1784                 }
1785
1786                 argv1 = argv[1];
1787                 if ( strncasecmp( argv1, "bindmethod=", STRLENOF( "bindmethod=" ) ) == 0 ) {
1788                         argv1 += STRLENOF( "bindmethod=" );
1789                 }
1790
1791                 if ( strcasecmp( argv1, "none" ) == 0 ) {
1792                         /* FIXME: is this at all useful? */
1793                         li->idassert_authmethod = LDAP_AUTH_NONE;
1794
1795                         if ( argc != 2 ) {
1796                                 fprintf( stderr,
1797         "%s: line %d: trailing args in \"%s %s ...\" line ignored\"\n",
1798                                         fname, lineno, argv[0], argv[1] );
1799                         }
1800
1801                 } else if ( strcasecmp( argv1, "simple" ) == 0 ) {
1802                         int     arg;
1803
1804                         for ( arg = 2; arg < argc; arg++ ) {
1805                                 if ( strncasecmp( argv[arg], "authcdn=", STRLENOF( "authcdn=" ) ) == 0 ) {
1806                                         char            *val = argv[arg] + STRLENOF( "authcdn=" );
1807                                         struct berval   dn;
1808                                         int             rc;
1809
1810                                         if ( !BER_BVISNULL( &li->idassert_authcDN ) ) {
1811                                                 fprintf( stderr, "%s: line %d: "
1812                                                                 "SASL authcDN already defined; replacing...\n",
1813                                                                 fname, lineno );
1814                                                 ch_free( li->idassert_authcDN.bv_val );
1815                                         }
1816                                         if ( strncasecmp( argv[arg], "dn:", STRLENOF( "dn:" ) ) == 0 ) {
1817                                                 val += STRLENOF( "dn:" );
1818                                         }
1819
1820                                         ber_str2bv( val, 0, 0, &dn );
1821                                         rc = dnNormalize( 0, NULL, NULL, &dn, &li->idassert_authcDN, NULL );
1822                                         if ( rc != LDAP_SUCCESS ) {
1823                                                 Debug( LDAP_DEBUG_ANY,
1824                                                         "%s: line %d: SASL authcdn \"%s\" is not a valid DN\n",
1825                                                         fname, lineno, val );
1826                                                 return 1;
1827                                         }
1828
1829                                 } else if ( strncasecmp( argv[arg], "cred=", STRLENOF( "cred=" ) ) == 0 ) {
1830                                         char    *val = argv[arg] + STRLENOF( "cred=" );
1831
1832                                         if ( !BER_BVISNULL( &li->idassert_passwd ) ) {
1833                                                 fprintf( stderr, "%s: line %d: "
1834                                                                 "SASL cred already defined; replacing...\n",
1835                                                                 fname, lineno );
1836                                                 ch_free( li->idassert_passwd.bv_val );
1837                                         }
1838                                         ber_str2bv( val, 0, 1, &li->idassert_passwd );
1839
1840                                 } else {
1841                                         fprintf( stderr, "%s: line %d: "
1842                                                         "unknown parameter %s\n",
1843                                                         fname, lineno, argv[arg] );
1844                                         return 1;
1845                                 }
1846                         }
1847
1848                         li->idassert_authmethod = LDAP_AUTH_SIMPLE;
1849
1850                 } else if ( strcasecmp( argv1, "sasl" ) == 0 ) {
1851 #ifdef HAVE_CYRUS_SASL
1852                         int     arg;
1853
1854                         for ( arg = 2; arg < argc; arg++ ) {
1855                                 if ( strncasecmp( argv[arg], "mech=", STRLENOF( "mech=" ) ) == 0 ) {
1856                                         char    *val = argv[arg] + STRLENOF( "mech=" );
1857
1858                                         if ( !BER_BVISNULL( &li->idassert_sasl_mech ) ) {
1859                                                 fprintf( stderr, "%s: line %d: "
1860                                                                 "SASL mech already defined; replacing...\n",
1861                                                                 fname, lineno );
1862                                                 ch_free( li->idassert_sasl_mech.bv_val );
1863                                         }
1864                                         ber_str2bv( val, 0, 1, &li->idassert_sasl_mech );
1865
1866                                 } else if ( strncasecmp( argv[arg], "realm=", STRLENOF( "realm=" ) ) == 0 ) {
1867                                         char    *val = argv[arg] + STRLENOF( "realm=" );
1868
1869                                         if ( !BER_BVISNULL( &li->idassert_sasl_realm ) ) {
1870                                                 fprintf( stderr, "%s: line %d: "
1871                                                                 "SASL realm already defined; replacing...\n",
1872                                                                 fname, lineno );
1873                                                 ch_free( li->idassert_sasl_realm.bv_val );
1874                                         }
1875                                         ber_str2bv( val, 0, 1, &li->idassert_sasl_realm );
1876
1877                                 } else if ( strncasecmp( argv[arg], "authcdn=", STRLENOF( "authcdn=" ) ) == 0 ) {
1878                                         char            *val = argv[arg] + STRLENOF( "authcdn=" );
1879                                         struct berval   dn;
1880                                         int             rc;
1881
1882                                         if ( !BER_BVISNULL( &li->idassert_authcDN ) ) {
1883                                                 fprintf( stderr, "%s: line %d: "
1884                                                                 "SASL authcDN already defined; replacing...\n",
1885                                                                 fname, lineno );
1886                                                 ch_free( li->idassert_authcDN.bv_val );
1887                                         }
1888                                         if ( strncasecmp( argv[arg], "dn:", STRLENOF( "dn:" ) ) == 0 ) {
1889                                                 val += STRLENOF( "dn:" );
1890                                         }
1891
1892                                         ber_str2bv( val, 0, 0, &dn );
1893                                         rc = dnNormalize( 0, NULL, NULL, &dn, &li->idassert_authcDN, NULL );
1894                                         if ( rc != LDAP_SUCCESS ) {
1895                                                 Debug( LDAP_DEBUG_ANY,
1896                                                         "%s: line %d: SASL authcdn \"%s\" is not a valid DN\n",
1897                                                         fname, lineno, val );
1898                                                 return 1;
1899                                         }
1900
1901                                 } else if ( strncasecmp( argv[arg], "authcid=", STRLENOF( "authcid=" ) ) == 0 ) {
1902                                         char    *val = argv[arg] + STRLENOF( "authcid=" );
1903
1904                                         if ( !BER_BVISNULL( &li->idassert_authcID ) ) {
1905                                                 fprintf( stderr, "%s: line %d: "
1906                                                                 "SASL authcID already defined; replacing...\n",
1907                                                                 fname, lineno );
1908                                                 ch_free( li->idassert_authcID.bv_val );
1909                                         }
1910                                         if ( strncasecmp( argv[arg], "u:", STRLENOF( "u:" ) ) == 0 ) {
1911                                                 val += STRLENOF( "u:" );
1912                                         }
1913                                         ber_str2bv( val, 0, 1, &li->idassert_authcID );
1914
1915                                 } else if ( strncasecmp( argv[arg], "cred=", STRLENOF( "cred=" ) ) == 0 ) {
1916                                         char    *val = argv[arg] + STRLENOF( "cred=" );
1917
1918                                         if ( !BER_BVISNULL( &li->idassert_passwd ) ) {
1919                                                 fprintf( stderr, "%s: line %d: "
1920                                                                 "SASL cred already defined; replacing...\n",
1921                                                                 fname, lineno );
1922                                                 ch_free( li->idassert_passwd.bv_val );
1923                                         }
1924                                         ber_str2bv( val, 0, 1, &li->idassert_passwd );
1925
1926                                 } else if ( strncasecmp( argv[arg], "authz=", STRLENOF( "authz=" ) ) == 0 ) {
1927                                         char    *val = argv[arg] + STRLENOF( "authz=" );
1928
1929                                         if ( strcasecmp( val, "proxyauthz" ) == 0 ) {
1930                                                 li->idassert_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
1931
1932                                         } else if ( strcasecmp( val, "native" ) == 0 ) {
1933                                                 li->idassert_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
1934
1935                                         } else {
1936                                                 fprintf( stderr, "%s: line %d: "
1937                                                         "unknown authz mode \"%s\"\n",
1938                                                         fname, lineno, val );
1939                                                 return 1;
1940                                         }
1941
1942                                 } else {
1943                                         fprintf( stderr, "%s: line %d: "
1944                                                         "unknown SASL parameter %s\n",
1945                                                         fname, lineno, argv[arg] );
1946                                         return 1;
1947                                 }
1948                         }
1949
1950                         li->idassert_authmethod = LDAP_AUTH_SASL;
1951
1952 #else /* !HAVE_CYRUS_SASL */
1953                         fprintf( stderr, "%s: line %d: "
1954                                         "compile --with-cyrus-sasl to enable SASL auth\n",
1955                                         fname, lineno );
1956                         return 1;
1957 #endif /* !HAVE_CYRUS_SASL */
1958
1959                 } else {
1960                         fprintf( stderr, "%s: line %d: "
1961                                         "unhandled idassert-method method %s\n",
1962                                         fname, lineno, argv[1] );
1963                         return 1;
1964                 }
1965
1966         } else {
1967                 return SLAP_CONF_UNKNOWN;
1968         }
1969
1970         return 0;
1971 }
1972
1973 static int
1974 parse_acl_auth(
1975     BackendDB   *be,
1976     const char  *fname,
1977     int         lineno,
1978     int         argc,
1979     char        **argv
1980 )
1981 {
1982         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
1983
1984         /* name to use for remote ACL access */
1985         if ( strcasecmp( argv[0], "acl-authcdn" ) == 0
1986                         || strcasecmp( argv[0], "binddn" ) == 0 )
1987         {
1988                 struct berval   dn;
1989                 int             rc;
1990
1991                 /* FIXME: "binddn" is no longer documented, and
1992                  * temporarily supported for backwards compatibility */
1993
1994                 if ( argc != 2 ) {
1995                         fprintf( stderr,
1996         "%s: line %d: missing name in \"%s <name>\" line\n",
1997                             fname, lineno, argv[0] );
1998                         return( 1 );
1999                 }
2000
2001                 if ( !BER_BVISNULL( &li->acl_authcDN ) ) {
2002                         fprintf( stderr, "%s: line %d: "
2003                                         "authcDN already defined; replacing...\n",
2004                                         fname, lineno );
2005                         ch_free( li->acl_authcDN.bv_val );
2006                 }
2007                 
2008                 ber_str2bv( argv[1], 0, 0, &dn );
2009                 rc = dnNormalize( 0, NULL, NULL, &dn, &li->acl_authcDN, NULL );
2010                 if ( rc != LDAP_SUCCESS ) {
2011                         Debug( LDAP_DEBUG_ANY,
2012                                 "%s: line %d: acl ID \"%s\" is not a valid DN\n",
2013                                 fname, lineno, argv[1] );
2014                         return 1;
2015                 }
2016
2017         /* password to use for remote ACL access */
2018         } else if ( strcasecmp( argv[0], "acl-passwd" ) == 0
2019                         || strcasecmp( argv[0], "bindpw" ) == 0 )
2020         {
2021                 /* FIXME: "bindpw" is no longer documented, and
2022                  * temporarily supported for backwards compatibility */
2023
2024                 if ( argc != 2 ) {
2025                         fprintf( stderr,
2026         "%s: line %d: missing password in \"%s <password>\" line\n",
2027                             fname, lineno, argv[0] );
2028                         return( 1 );
2029                 }
2030
2031                 if ( !BER_BVISNULL( &li->acl_passwd ) ) {
2032                         fprintf( stderr, "%s: line %d: "
2033                                         "passwd already defined; replacing...\n",
2034                                         fname, lineno );
2035                         ch_free( li->acl_passwd.bv_val );
2036                 }
2037                 
2038                 ber_str2bv( argv[1], 0, 1, &li->acl_passwd );
2039
2040         } else if ( strcasecmp( argv[0], "acl-method" ) == 0 ) {
2041                 char    *argv1;
2042
2043                 if ( argc < 2 ) {
2044                         fprintf( stderr,
2045         "%s: line %d: missing method in \"%s <method>\" line\n",
2046                             fname, lineno, argv[0] );
2047                         return( 1 );
2048                 }
2049
2050                 argv1 = argv[1];
2051                 if ( strncasecmp( argv1, "bindmethod=", STRLENOF( "bindmethod=" ) ) == 0 ) {
2052                         argv1 += STRLENOF( "bindmethod=" );
2053                 }
2054
2055                 if ( strcasecmp( argv1, "none" ) == 0 ) {
2056                         /* FIXME: is this at all useful? */
2057                         li->acl_authmethod = LDAP_AUTH_NONE;
2058
2059                         if ( argc != 2 ) {
2060                                 fprintf( stderr,
2061         "%s: line %d: trailing args in \"%s %s ...\" line ignored\"\n",
2062                                         fname, lineno, argv[0], argv[1] );
2063                         }
2064
2065                 } else if ( strcasecmp( argv1, "simple" ) == 0 ) {
2066                         li->acl_authmethod = LDAP_AUTH_SIMPLE;
2067
2068                         if ( argc != 2 ) {
2069                                 fprintf( stderr,
2070         "%s: line %d: trailing args in \"%s %s ...\" line ignored\"\n",
2071                                         fname, lineno, argv[0], argv[1] );
2072                         }
2073
2074                 } else if ( strcasecmp( argv1, "sasl" ) == 0 ) {
2075 #ifdef HAVE_CYRUS_SASL
2076                         int     arg;
2077
2078                         for ( arg = 2; arg < argc; arg++ ) {
2079                                 if ( strncasecmp( argv[arg], "mech=", STRLENOF( "mech=" ) ) == 0 ) {
2080                                         char    *val = argv[arg] + STRLENOF( "mech=" );
2081
2082                                         if ( !BER_BVISNULL( &li->acl_sasl_mech ) ) {
2083                                                 fprintf( stderr, "%s: line %d: "
2084                                                                 "SASL mech already defined; replacing...\n",
2085                                                                 fname, lineno );
2086                                                 ch_free( li->acl_sasl_mech.bv_val );
2087                                         }
2088                                         ber_str2bv( val, 0, 1, &li->acl_sasl_mech );
2089
2090                                 } else if ( strncasecmp( argv[arg], "realm=", STRLENOF( "realm=" ) ) == 0 ) {
2091                                         char    *val = argv[arg] + STRLENOF( "realm=" );
2092
2093                                         if ( !BER_BVISNULL( &li->acl_sasl_realm ) ) {
2094                                                 fprintf( stderr, "%s: line %d: "
2095                                                                 "SASL realm already defined; replacing...\n",
2096                                                                 fname, lineno );
2097                                                 ch_free( li->acl_sasl_realm.bv_val );
2098                                         }
2099                                         ber_str2bv( val, 0, 1, &li->acl_sasl_realm );
2100
2101                                 } else if ( strncasecmp( argv[arg], "authcdn=", STRLENOF( "authcdn=" ) ) == 0 ) {
2102                                         char            *val = argv[arg] + STRLENOF( "authcdn=" );
2103                                         struct berval   dn;
2104                                         int             rc;
2105
2106                                         if ( !BER_BVISNULL( &li->acl_authcDN ) ) {
2107                                                 fprintf( stderr, "%s: line %d: "
2108                                                                 "SASL authcDN already defined; replacing...\n",
2109                                                                 fname, lineno );
2110                                                 ch_free( li->acl_authcDN.bv_val );
2111                                         }
2112                                         if ( strncasecmp( argv[arg], "dn:", STRLENOF( "dn:" ) ) == 0 ) {
2113                                                 val += STRLENOF( "dn:" );
2114                                         }
2115
2116                                         ber_str2bv( val, 0, 0, &dn );
2117                                         rc = dnNormalize( 0, NULL, NULL, &dn, &li->acl_authcDN, NULL );
2118                                         if ( rc != LDAP_SUCCESS ) {
2119                                                 Debug( LDAP_DEBUG_ANY,
2120                                                         "%s: line %d: SASL authcdn \"%s\" is not a valid DN\n",
2121                                                         fname, lineno, val );
2122                                                 return 1;
2123                                         }
2124
2125                                 } else if ( strncasecmp( argv[arg], "authcid=", STRLENOF( "authcid=" ) ) == 0 ) {
2126                                         char    *val = argv[arg] + STRLENOF( "authcid=" );
2127
2128                                         if ( !BER_BVISNULL( &li->acl_authcID ) ) {
2129                                                 fprintf( stderr, "%s: line %d: "
2130                                                                 "SASL authcID already defined; replacing...\n",
2131                                                                 fname, lineno );
2132                                                 ch_free( li->acl_authcID.bv_val );
2133                                         }
2134                                         if ( strncasecmp( argv[arg], "u:", STRLENOF( "u:" ) ) == 0 ) {
2135                                                 val += STRLENOF( "u:" );
2136                                         }
2137                                         ber_str2bv( val, 0, 1, &li->acl_authcID );
2138
2139                                 } else if ( strncasecmp( argv[arg], "cred=", STRLENOF( "cred=" ) ) == 0 ) {
2140                                         char    *val = argv[arg] + STRLENOF( "cred=" );
2141
2142                                         if ( !BER_BVISNULL( &li->acl_passwd ) ) {
2143                                                 fprintf( stderr, "%s: line %d: "
2144                                                                 "SASL cred already defined; replacing...\n",
2145                                                                 fname, lineno );
2146                                                 ch_free( li->acl_passwd.bv_val );
2147                                         }
2148                                         ber_str2bv( val, 0, 1, &li->acl_passwd );
2149
2150                                 } else {
2151                                         fprintf( stderr, "%s: line %d: "
2152                                                         "unknown SASL parameter %s\n",
2153                                                         fname, lineno, argv[arg] );
2154                                         return 1;
2155                                 }
2156                         }
2157
2158                         li->acl_authmethod = LDAP_AUTH_SASL;
2159
2160 #else /* !HAVE_CYRUS_SASL */
2161                         fprintf( stderr, "%s: line %d: "
2162                                         "compile --with-cyrus-sasl to enable SASL auth\n",
2163                                         fname, lineno );
2164                         return 1;
2165 #endif /* !HAVE_CYRUS_SASL */
2166
2167                 } else {
2168                         fprintf( stderr, "%s: line %d: "
2169                                         "unhandled acl-method method %s\n",
2170                                         fname, lineno, argv[1] );
2171                         return 1;
2172                 }
2173
2174         } else {
2175                 return SLAP_CONF_UNKNOWN;
2176         }
2177
2178         return 0;
2179 }
2180