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