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