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