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