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