]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/config.c
d728a584f6fc5fba21b51cc2102d072bf18bbcdb
[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-2006 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_TIMEOUT,
63         LDAP_BACK_CFG_IDLE_TIMEOUT,
64         LDAP_BACK_CFG_CONN_TTL,
65         LDAP_BACK_CFG_NETWORK_TIMEOUT,
66         LDAP_BACK_CFG_VERSION,
67         LDAP_BACK_CFG_REWRITE,
68
69         LDAP_BACK_CFG_LAST
70 };
71
72 static ConfigTable ldapcfg[] = {
73         { "uri", "uri", 2, 2, 0,
74                 ARG_MAGIC|LDAP_BACK_CFG_URI,
75                 ldap_back_cf_gen, "( OLcfgDbAt:0.14 "
76                         "NAME 'olcDbURI' "
77                         "DESC 'URI (list) for remote DSA' "
78                         "SYNTAX OMsDirectoryString "
79                         "SINGLE-VALUE )",
80                 NULL, NULL },
81         { "tls", "what", 2, 2, 0,
82                 ARG_MAGIC|LDAP_BACK_CFG_TLS,
83                 ldap_back_cf_gen, "( OLcfgDbAt:3.1 "
84                         "NAME 'olcDbStartTLS' "
85                         "DESC 'StartTLS' "
86                         "SYNTAX OMsDirectoryString "
87                         "SINGLE-VALUE )",
88                 NULL, NULL },
89         { "acl-authcDN", "DN", 2, 2, 0,
90                 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_ACL_AUTHCDN,
91                 ldap_back_cf_gen, "( OLcfgDbAt:3.2 "
92                         "NAME 'olcDbACLAuthcDn' "
93                         "DESC 'Remote ACL administrative identity' "
94                         "OBSOLETE "
95                         "SYNTAX OMsDN "
96                         "SINGLE-VALUE )",
97                 NULL, NULL },
98         /* deprecated, will be removed; aliases "acl-authcDN" */
99         { "binddn", "DN", 2, 2, 0,
100                 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_ACL_AUTHCDN,
101                 ldap_back_cf_gen, NULL, NULL, NULL },
102         { "acl-passwd", "cred", 2, 2, 0,
103                 ARG_MAGIC|LDAP_BACK_CFG_ACL_PASSWD,
104                 ldap_back_cf_gen, "( OLcfgDbAt:3.3 "
105                         "NAME 'olcDbACLPasswd' "
106                         "DESC 'Remote ACL administrative identity credentials' "
107                         "OBSOLETE "
108                         "SYNTAX OMsDirectoryString "
109                         "SINGLE-VALUE )",
110                 NULL, NULL },
111         /* deprecated, will be removed; aliases "acl-passwd" */
112         { "bindpw", "cred", 2, 2, 0,
113                 ARG_MAGIC|LDAP_BACK_CFG_ACL_PASSWD,
114                 ldap_back_cf_gen, NULL, NULL, NULL },
115         /* deprecated, will be removed; aliases "acl-bind" */
116         { "acl-method", "args", 2, 0, 0,
117                 ARG_MAGIC|LDAP_BACK_CFG_ACL_METHOD,
118                 ldap_back_cf_gen, NULL, NULL, NULL },
119         { "acl-bind", "args", 2, 0, 0,
120                 ARG_MAGIC|LDAP_BACK_CFG_ACL_BIND,
121                 ldap_back_cf_gen, "( OLcfgDbAt:3.4 "
122                         "NAME 'olcDbACLBind' "
123                         "DESC 'Remote ACL administrative identity auth bind configuration' "
124                         "SYNTAX OMsDirectoryString "
125                         "SINGLE-VALUE )",
126                 NULL, NULL },
127         { "idassert-authcDN", "DN", 2, 2, 0,
128                 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHCDN,
129                 ldap_back_cf_gen, "( OLcfgDbAt:3.5 "
130                         "NAME 'olcDbIDAssertAuthcDn' "
131                         "DESC 'Remote Identity Assertion administrative identity' "
132                         "OBSOLETE "
133                         "SYNTAX OMsDN "
134                         "SINGLE-VALUE )",
135                 NULL, NULL },
136         /* deprecated, will be removed; partially aliases "idassert-authcDN" */
137         { "proxyauthzdn", "DN", 2, 2, 0,
138                 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHCDN,
139                 ldap_back_cf_gen, NULL, NULL, NULL },
140         { "idassert-passwd", "cred", 2, 2, 0,
141                 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_PASSWD,
142                 ldap_back_cf_gen, "( OLcfgDbAt:3.6 "
143                         "NAME 'olcDbIDAssertPasswd' "
144                         "DESC 'Remote Identity Assertion administrative identity credentials' "
145                         "OBSOLETE "
146                         "SYNTAX OMsDirectoryString "
147                         "SINGLE-VALUE )",
148                 NULL, NULL },
149         /* deprecated, will be removed; partially aliases "idassert-passwd" */
150         { "proxyauthzpw", "cred", 2, 2, 0,
151                 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_PASSWD,
152                 ldap_back_cf_gen, NULL, NULL, NULL },
153         { "idassert-bind", "args", 2, 0, 0,
154                 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND,
155                 ldap_back_cf_gen, "( OLcfgDbAt:3.7 "
156                         "NAME 'olcDbIDAssertBind' "
157                         "DESC 'Remote Identity Assertion administrative identity auth bind configuration' "
158                         "SYNTAX OMsDirectoryString "
159                         "SINGLE-VALUE )",
160                 NULL, NULL },
161         { "idassert-method", "args", 2, 0, 0,
162                 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_METHOD,
163                 ldap_back_cf_gen, NULL, NULL, NULL },
164         { "idassert-mode", "mode>|u:<user>|[dn:]<DN", 2, 0, 0,
165                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_MODE,
166                 ldap_back_cf_gen, "( OLcfgDbAt:3.8 "
167                         "NAME 'olcDbIDAssertMode' "
168                         "DESC 'Remote Identity Assertion mode' "
169                         "OBSOLETE "
170                         "SYNTAX OMsDirectoryString "
171                         "SINGLE-VALUE)",
172                 NULL, NULL },
173         { "idassert-authzFrom", "authzRule", 2, 2, 0,
174                 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHZFROM,
175                 ldap_back_cf_gen, "( OLcfgDbAt:3.9 "
176                         "NAME 'olcDbIDAssertAuthzFrom' "
177                         "DESC 'Remote Identity Assertion authz rules' "
178                         "SYNTAX OMsDirectoryString "
179                         "X-ORDERED 'VALUES' )",
180                 NULL, NULL },
181         { "rebind-as-user", "NO|yes", 1, 2, 0,
182                 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND,
183                 ldap_back_cf_gen, "( OLcfgDbAt:3.10 "
184                         "NAME 'olcDbRebindAsUser' "
185                         "DESC 'Rebind as user' "
186                         "SYNTAX OMsBoolean "
187                         "SINGLE-VALUE )",
188                 NULL, NULL },
189         { "chase-referrals", "YES|no", 2, 2, 0,
190                 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE,
191                 ldap_back_cf_gen, "( OLcfgDbAt:3.11 "
192                         "NAME 'olcDbChaseReferrals' "
193                         "DESC 'Chase referrals' "
194                         "SYNTAX OMsBoolean "
195                         "SINGLE-VALUE )",
196                 NULL, NULL },
197         { "t-f-support", "NO|yes|discover", 2, 2, 0,
198                 ARG_MAGIC|LDAP_BACK_CFG_T_F,
199                 ldap_back_cf_gen, "( OLcfgDbAt:3.12 "
200                         "NAME 'olcDbTFSupport' "
201                         "DESC 'Absolute filters support' "
202                         "SYNTAX OMsDirectoryString "
203                         "SINGLE-VALUE )",
204                 NULL, NULL },
205         { "proxy-whoami", "NO|yes", 1, 2, 0,
206                 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_WHOAMI,
207                 ldap_back_cf_gen, "( OLcfgDbAt:3.13 "
208                         "NAME 'olcDbProxyWhoAmI' "
209                         "DESC 'Proxy whoAmI exop' "
210                         "SYNTAX OMsBoolean "
211                         "SINGLE-VALUE )",
212                 NULL, NULL },
213         { "timeout", "timeout(list)", 2, 0, 0,
214                 ARG_MAGIC|LDAP_BACK_CFG_TIMEOUT,
215                 ldap_back_cf_gen, "( OLcfgDbAt:3.14 "
216                         "NAME 'olcDbTimeout' "
217                         "DESC 'Per-operation timeouts' "
218                         "SYNTAX OMsDirectoryString "
219                         "SINGLE-VALUE )",
220                 NULL, NULL },
221         { "idle-timeout", "timeout", 2, 0, 0,
222                 ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT,
223                 ldap_back_cf_gen, "( OLcfgDbAt:3.15 "
224                         "NAME 'olcDbIdleTimeout' "
225                         "DESC 'connection idle timeout' "
226                         "SYNTAX OMsDirectoryString "
227                         "SINGLE-VALUE )",
228                 NULL, NULL },
229         { "conn-ttl", "ttl", 2, 0, 0,
230                 ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL,
231                 ldap_back_cf_gen, "( OLcfgDbAt:3.16 "
232                         "NAME 'olcDbConnTtl' "
233                         "DESC 'connection ttl' "
234                         "SYNTAX OMsDirectoryString "
235                         "SINGLE-VALUE )",
236                 NULL, NULL },
237         { "network-timeout", "timeout", 2, 0, 0,
238                 ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT,
239                 ldap_back_cf_gen, "( OLcfgDbAt:3.17 "
240                         "NAME 'olcDbNetworkTimeout' "
241                         "DESC 'connection network timeout' "
242                         "SYNTAX OMsDirectoryString "
243                         "SINGLE-VALUE )",
244                 NULL, NULL },
245         { "protocol-version", "version", 2, 0, 0,
246                 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION,
247                 ldap_back_cf_gen, "( OLcfgDbAt:3.18 "
248                         "NAME 'olcDbProtocolVersion' "
249                         "DESC 'protocol version' "
250                         "SYNTAX OMsInteger "
251                         "SINGLE-VALUE )",
252                 NULL, NULL },
253         { "suffixmassage", "[virtual]> <real", 2, 3, 0,
254                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
255                 ldap_back_cf_gen, NULL, NULL, NULL },
256         { "map", "attribute|objectClass> [*|<local>] *|<remote", 3, 4, 0,
257                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
258                 ldap_back_cf_gen, NULL, NULL, NULL },
259         { "rewrite", "<arglist>", 2, 4, STRLENOF( "rewrite" ),
260                 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
261                 ldap_back_cf_gen, NULL, NULL, NULL },
262         { NULL, NULL, 0, 0, 0, ARG_IGNORED,
263                 NULL, NULL, NULL, NULL }
264 };
265
266 static ConfigOCs ldapocs[] = {
267         { "( OLcfgDbOc:3.1 "
268                 "NAME 'olcLDAPConfig' "
269                 "DESC 'LDAP backend configuration' "
270                 "SUP olcDatabaseConfig "
271                 "MUST olcDbURI "
272                 "MAY ( olcDbStartTLS "
273                         "$ olcDbACLAuthcDn "
274                         "$ olcDbACLPasswd "
275                         "$ olcDbACLBind "
276                         "$ olcDbIDAssertAuthcDn "
277                         "$ olcDbIDAssertPasswd "
278                         "$ olcDbIDAssertBind "
279                         "$ olcDbIDAssertMode "
280                         "$ olcDbIDAssertAuthzFrom "
281                         "$ olcDbRebindAsUser "
282                         "$ olcDbChaseReferrals "
283                         "$ olcDbTFSupport "
284                         "$ olcDbProxyWhoAmI "
285                         "$ olcDbTimeout "
286                         "$ olcDbIdleTimeout "
287                 ") )",
288                         Cft_Database, ldapcfg},
289         { NULL, 0, NULL }
290 };
291
292 static slap_verbmasks idassert_mode[] = {
293         { BER_BVC("self"),              LDAP_BACK_IDASSERT_SELF },
294         { BER_BVC("anonymous"),         LDAP_BACK_IDASSERT_ANONYMOUS },
295         { BER_BVC("none"),              LDAP_BACK_IDASSERT_NOASSERT },
296         { BER_BVC("legacy"),            LDAP_BACK_IDASSERT_LEGACY },
297         { BER_BVNULL,                   0 }
298 };
299
300 static slap_verbmasks tls_mode[] = {
301         { BER_BVC( "propagate" ),       LDAP_BACK_F_TLS_PROPAGATE_MASK },
302         { BER_BVC( "try-propagate" ),   LDAP_BACK_F_PROPAGATE_TLS },
303         { BER_BVC( "start" ),           LDAP_BACK_F_TLS_USE_MASK },
304         { BER_BVC( "try-start" ),       LDAP_BACK_F_USE_TLS },
305         { BER_BVC( "none" ),            LDAP_BACK_F_NONE },
306         { BER_BVNULL,                   0 }
307 };
308
309 static slap_verbmasks t_f_mode[] = {
310         { BER_BVC( "yes" ),             LDAP_BACK_F_SUPPORT_T_F },
311         { BER_BVC( "discover" ),        LDAP_BACK_F_SUPPORT_T_F_DISCOVER },
312         { BER_BVC( "no" ),              LDAP_BACK_F_NONE },
313         { BER_BVNULL,                   0 }
314 };
315
316 static slap_cf_aux_table timeout_table[] = {
317         { BER_BVC("add="), 0 * sizeof( time_t ), 'u', 0, NULL },
318         { BER_BVC("delete="), 1 * sizeof( time_t ), 'u', 0, NULL },
319         { BER_BVC("modify="), 2 * sizeof( time_t ), 'u', 0, NULL },
320         { BER_BVC("modrdn="), 3 * sizeof( time_t ), 'u', 0, NULL },
321         { BER_BVNULL, 0, 0, 0, NULL }
322 };
323
324 static int
325 ldap_back_cf_gen( ConfigArgs *c )
326 {
327         ldapinfo_t      *li = ( ldapinfo_t * )c->be->be_private;
328         int             rc;
329         int             i;
330
331         if ( c->op == SLAP_CONFIG_EMIT ) {
332                 struct berval   bv = BER_BVNULL;
333                 rc = 0;
334
335                 if ( li == NULL ) {
336                         return 1;
337                 }
338
339                 switch( c->type ) {
340                 case LDAP_BACK_CFG_URI:
341                         if ( li->li_uri != NULL ) {
342                                 struct berval   bv;
343
344                                 ber_str2bv( li->li_uri, 0, 0, &bv );
345                                 value_add_one( &c->rvalue_vals, &bv );
346
347                         } else {
348                                 rc = 1;
349                         }
350                         break;
351
352                 case LDAP_BACK_CFG_TLS:
353                         enum_to_verb( tls_mode, ( li->li_flags & LDAP_BACK_F_TLS_MASK ), &bv );
354                         assert( !BER_BVISNULL( &bv ) );
355                         value_add_one( &c->rvalue_vals, &bv );
356                         break;
357
358                 case LDAP_BACK_CFG_ACL_AUTHCDN:
359                 case LDAP_BACK_CFG_ACL_PASSWD:
360                 case LDAP_BACK_CFG_ACL_METHOD:
361                         /* handled by LDAP_BACK_CFG_ACL_BIND */
362                         rc = 1;
363                         break;
364
365                 case LDAP_BACK_CFG_ACL_BIND: {
366                         int     i;
367
368                         if ( li->li_acl_authmethod == LDAP_AUTH_NONE ) {
369                                 return 1;
370                         }
371
372                         bindconf_unparse( &li->li_acl, &bv );
373
374                         for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ )
375                                 /* count spaces */ ;
376
377                         if ( i ) {
378                                 bv.bv_len -= i;
379                                 AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ],
380                                         bv.bv_len + 1 );
381                         }
382
383                         ber_bvarray_add( &c->rvalue_vals, &bv );
384                         break;
385                 }
386
387                 case LDAP_BACK_CFG_IDASSERT_MODE:
388                 case LDAP_BACK_CFG_IDASSERT_AUTHCDN:
389                 case LDAP_BACK_CFG_IDASSERT_PASSWD:
390                 case LDAP_BACK_CFG_IDASSERT_METHOD:
391                         /* handled by LDAP_BACK_CFG_IDASSERT_BIND */
392                         rc = 1;
393                         break;
394
395                 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
396                         int             i;
397
398                         if ( li->li_idassert_authz == NULL ) {
399                                 rc = 1;
400                                 break;
401                         }
402
403                         for ( i = 0; !BER_BVISNULL( &li->li_idassert_authz[ i ] ); i++ )
404                         {
405                                 value_add_one( &c->rvalue_vals, &li->li_idassert_authz[ i ] );
406                         }
407                         break;
408                 }
409
410                 case LDAP_BACK_CFG_IDASSERT_BIND: {
411                         int             i;
412                         struct berval   bc = BER_BVNULL;
413                         char            *ptr;
414
415                         if ( li->li_idassert_authmethod == LDAP_AUTH_NONE ) {
416                                 return 1;
417                         }
418
419                         if ( li->li_idassert_authmethod != LDAP_AUTH_NONE ) {
420                                 ber_len_t       len;
421
422                                 switch ( li->li_idassert_mode ) {
423                                 case LDAP_BACK_IDASSERT_OTHERID:
424                                 case LDAP_BACK_IDASSERT_OTHERDN:
425                                         break;
426
427                                 default: {
428                                         struct berval   mode = BER_BVNULL;
429
430                                         enum_to_verb( idassert_mode, li->li_idassert_mode, &mode );
431                                         if ( BER_BVISNULL( &mode ) ) {
432                                                 /* there's something wrong... */
433                                                 assert( 0 );
434                                                 rc = 1;
435         
436                                         } else {
437                                                 bv.bv_len = STRLENOF( "mode=" ) + mode.bv_len;
438                                                 bv.bv_val = ch_malloc( bv.bv_len + 1 );
439
440                                                 ptr = lutil_strcopy( bv.bv_val, "mode=" );
441                                                 ptr = lutil_strcopy( ptr, mode.bv_val );
442                                         }
443                                         break;
444                                 }
445                                 }
446
447                                 if ( li->li_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) {
448                                         len = bv.bv_len + STRLENOF( "authz=native" );
449
450                                         if ( !BER_BVISEMPTY( &bv ) ) {
451                                                 len += STRLENOF( " " );
452                                         }
453
454                                         bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
455
456                                         ptr = &bv.bv_val[ bv.bv_len ];
457
458                                         if ( !BER_BVISEMPTY( &bv ) ) {
459                                                 ptr = lutil_strcopy( ptr, " " );
460                                         }
461
462                                         (void)lutil_strcopy( ptr, "authz=native" );
463                                 }
464
465                                 len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override,obsolete-encoding-workaround" );
466                                 /* flags */
467                                 if ( !BER_BVISEMPTY( &bv ) ) {
468                                         len += STRLENOF( " " );
469                                 }
470
471                                 bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
472
473                                 ptr = &bv.bv_val[ bv.bv_len ];
474
475                                 if ( !BER_BVISEMPTY( &bv ) ) {
476                                         ptr = lutil_strcopy( ptr, " " );
477                                 }
478
479                                 ptr = lutil_strcopy( ptr, "flags=" );
480
481                                 if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
482                                         ptr = lutil_strcopy( ptr, "prescriptive" );
483                                 } else {
484                                         ptr = lutil_strcopy( ptr, "non-prescriptive" );
485                                 }
486
487                                 if ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
488                                         ptr = lutil_strcopy( ptr, ",override" );
489                                 }
490
491                                 if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
492                                         ptr = lutil_strcopy( ptr, ",obsolete-proxy-authz" );
493
494                                 } else if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
495                                         ptr = lutil_strcopy( ptr, ",obsolete-encoding-workaround" );
496                                 }
497
498                                 bv.bv_len = ( ptr - bv.bv_val );
499                                 /* end-of-flags */
500                         }
501
502                         bindconf_unparse( &li->li_idassert, &bc );
503
504                         if ( !BER_BVISNULL( &bv ) ) {
505                                 ber_len_t       len = bv.bv_len + bc.bv_len;
506
507                                 bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
508
509                                 assert( bc.bv_val[ 0 ] == ' ' );
510
511                                 ptr = lutil_strcopy( &bv.bv_val[ bv.bv_len ], bc.bv_val );
512                                 free( bc.bv_val );
513                                 bv.bv_len = ptr - bv.bv_val;
514
515                         } else {
516                                 for ( i = 0; isspace( (unsigned char) bc.bv_val[ i ] ); i++ )
517                                         /* count spaces */ ;
518
519                                 if ( i ) {
520                                         bc.bv_len -= i;
521                                         AC_MEMCPY( bc.bv_val, &bc.bv_val[ i ], bc.bv_len + 1 );
522                                 }
523
524                                 bv = bc;
525                         }
526                         
527                         ber_bvarray_add( &c->rvalue_vals, &bv );
528
529                         break;
530                 }
531
532                 case LDAP_BACK_CFG_REBIND:
533                         c->value_int = LDAP_BACK_SAVECRED( li );
534                         break;
535
536                 case LDAP_BACK_CFG_CHASE:
537                         c->value_int = LDAP_BACK_CHASE_REFERRALS( li );
538                         break;
539
540                 case LDAP_BACK_CFG_T_F:
541                         enum_to_verb( t_f_mode, (li->li_flags & LDAP_BACK_F_SUPPORT_T_F_MASK), &bv );
542                         if ( BER_BVISNULL( &bv ) ) {
543                                 /* there's something wrong... */
544                                 assert( 0 );
545                                 rc = 1;
546
547                         } else {
548                                 value_add_one( &c->rvalue_vals, &bv );
549                         }
550                         break;
551
552                 case LDAP_BACK_CFG_WHOAMI:
553                         c->value_int = LDAP_BACK_PROXY_WHOAMI( li );
554                         break;
555
556                 case LDAP_BACK_CFG_TIMEOUT:
557                         BER_BVZERO( &bv );
558
559                         for ( i = 0; i < LDAP_BACK_OP_LAST; i++ ) {
560                                 if ( li->li_timeout[ i ] != 0 ) {
561                                         break;
562                                 }
563                         }
564
565                         if ( i == LDAP_BACK_OP_LAST ) {
566                                 return 1;
567                         }
568
569                         slap_cf_aux_table_unparse( li->li_timeout, &bv, timeout_table );
570
571                         if ( BER_BVISNULL( &bv ) ) {
572                                 return 1;
573                         }
574
575                         for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ )
576                                 /* count spaces */ ;
577
578                         if ( i ) {
579                                 bv.bv_len -= i;
580                                 AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ],
581                                         bv.bv_len + 1 );
582                         }
583
584                         ber_bvarray_add( &c->rvalue_vals, &bv );
585                         break;
586
587                 case LDAP_BACK_CFG_IDLE_TIMEOUT: {
588                         char    buf[ SLAP_TEXT_BUFLEN ];
589
590                         if ( li->li_idle_timeout == 0 ) {
591                                 return 1;
592                         }
593
594                         lutil_unparse_time( buf, sizeof( buf ), li->li_idle_timeout );
595                         ber_str2bv( buf, 0, 0, &bv );
596                         value_add_one( &c->rvalue_vals, &bv );
597                         } break;
598
599                 case LDAP_BACK_CFG_CONN_TTL: {
600                         char    buf[ SLAP_TEXT_BUFLEN ];
601
602                         if ( li->li_conn_ttl == 0 ) {
603                                 return 1;
604                         }
605
606                         lutil_unparse_time( buf, sizeof( buf ), li->li_conn_ttl );
607                         ber_str2bv( buf, 0, 0, &bv );
608                         value_add_one( &c->rvalue_vals, &bv );
609                         } break;
610
611                 case LDAP_BACK_CFG_NETWORK_TIMEOUT: {
612                         char    buf[ SLAP_TEXT_BUFLEN ];
613
614                         if ( li->li_network_timeout == 0 ) {
615                                 return 1;
616                         }
617
618                         snprintf( buf, sizeof( buf ), "%ld",
619                                 (long)li->li_network_timeout );
620                         ber_str2bv( buf, 0, 0, &bv );
621                         value_add_one( &c->rvalue_vals, &bv );
622                         } break;
623
624                 case LDAP_BACK_CFG_VERSION:
625                         if ( li->li_version == 0 ) {
626                                 return 1;
627                         }
628
629                         c->value_int = li->li_version;
630                         break;
631
632                 default:
633                         /* FIXME: we need to handle all... */
634                         assert( 0 );
635                         break;
636                 }
637                 return rc;
638
639         } else if ( c->op == LDAP_MOD_DELETE ) {
640                 rc = 0;
641                 switch( c->type ) {
642                 case LDAP_BACK_CFG_URI:
643                         if ( li->li_uri != NULL ) {
644                                 ch_free( li->li_uri );
645                                 li->li_uri = NULL;
646
647                                 assert( li->li_bvuri != NULL );
648                                 ber_bvarray_free( li->li_bvuri );
649                                 li->li_bvuri = NULL;
650                         }
651
652                         /* better cleanup the cached connections... */
653                         /* NOTE: don't worry about locking: if we got here,
654                          * other threads are suspended. */
655                         if ( li->li_conninfo.lai_tree != NULL ) {
656                                 avl_free( li->li_conninfo.lai_tree, ldap_back_conn_free );
657                                 li->li_conninfo.lai_tree = NULL;
658                         }
659                         
660                         break;
661
662                 case LDAP_BACK_CFG_TLS:
663                         rc = 1;
664                         break;
665
666                 case LDAP_BACK_CFG_ACL_AUTHCDN:
667                 case LDAP_BACK_CFG_ACL_PASSWD:
668                 case LDAP_BACK_CFG_ACL_METHOD:
669                         /* handled by LDAP_BACK_CFG_ACL_BIND */
670                         rc = 1;
671                         break;
672
673                 case LDAP_BACK_CFG_ACL_BIND:
674                         bindconf_free( &li->li_acl );
675                         break;
676
677                 case LDAP_BACK_CFG_IDASSERT_MODE:
678                 case LDAP_BACK_CFG_IDASSERT_AUTHCDN:
679                 case LDAP_BACK_CFG_IDASSERT_PASSWD:
680                 case LDAP_BACK_CFG_IDASSERT_METHOD:
681                         /* handled by LDAP_BACK_CFG_IDASSERT_BIND */
682                         rc = 1;
683                         break;
684
685                 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM:
686                         if ( li->li_idassert_authz != NULL ) {
687                                 ber_bvarray_free( li->li_idassert_authz );
688                                 li->li_idassert_authz = NULL;
689                         }
690                         break;
691
692                 case LDAP_BACK_CFG_IDASSERT_BIND:
693                         bindconf_free( &li->li_idassert );
694                         break;
695
696                 case LDAP_BACK_CFG_REBIND:
697                 case LDAP_BACK_CFG_CHASE:
698                 case LDAP_BACK_CFG_T_F:
699                 case LDAP_BACK_CFG_WHOAMI:
700                         rc = 1;
701                         break;
702
703                 case LDAP_BACK_CFG_TIMEOUT:
704                         for ( i = 0; i < LDAP_BACK_OP_LAST; i++ ) {
705                                 li->li_timeout[ i ] = 0;
706                         }
707                         break;
708
709                 case LDAP_BACK_CFG_IDLE_TIMEOUT:
710                         li->li_idle_timeout = 0;
711                         break;
712
713                 case LDAP_BACK_CFG_CONN_TTL:
714                         li->li_conn_ttl = 0;
715                         break;
716
717                 case LDAP_BACK_CFG_NETWORK_TIMEOUT:
718                         li->li_network_timeout = 0;
719                         break;
720
721                 case LDAP_BACK_CFG_VERSION:
722                         li->li_version = 0;
723                         break;
724
725                 default:
726                         /* FIXME: we need to handle all... */
727                         assert( 0 );
728                         break;
729                 }
730                 return rc;
731
732         }
733
734         switch( c->type ) {
735         case LDAP_BACK_CFG_URI: {
736                 LDAPURLDesc     *tmpludp, *lud;
737                 char            **urllist = NULL;
738                 int             urlrc = LDAP_URL_SUCCESS, i;
739
740                 if ( li->li_uri != NULL ) {
741                         ch_free( li->li_uri );
742                         li->li_uri = NULL;
743
744                         assert( li->li_bvuri != NULL );
745                         ber_bvarray_free( li->li_bvuri );
746                         li->li_bvuri = NULL;
747                 }
748
749                 /* PARANOID: DN and more are not required nor allowed */
750                 urlrc = ldap_url_parselist_ext( &lud, c->argv[ 1 ], ", \t" );
751                 if ( urlrc != LDAP_URL_SUCCESS ) {
752                         char    *why;
753
754                         switch ( urlrc ) {
755                         case LDAP_URL_ERR_MEM:
756                                 why = "no memory";
757                                 break;
758                         case LDAP_URL_ERR_PARAM:
759                                 why = "parameter is bad";
760                                 break;
761                         case LDAP_URL_ERR_BADSCHEME:
762                                 why = "URL doesn't begin with \"[c]ldap[si]://\"";
763                                 break;
764                         case LDAP_URL_ERR_BADENCLOSURE:
765                                 why = "URL is missing trailing \">\"";
766                                 break;
767                         case LDAP_URL_ERR_BADURL:
768                                 why = "URL is bad";
769                                 break;
770                         case LDAP_URL_ERR_BADHOST:
771                                 why = "host/port is bad";
772                                 break;
773                         case LDAP_URL_ERR_BADATTRS:
774                                 why = "bad (or missing) attributes";
775                                 break;
776                         case LDAP_URL_ERR_BADSCOPE:
777                                 why = "scope string is invalid (or missing)";
778                                 break;
779                         case LDAP_URL_ERR_BADFILTER:
780                                 why = "bad or missing filter";
781                                 break;
782                         case LDAP_URL_ERR_BADEXTS:
783                                 why = "bad or missing extensions";
784                                 break;
785                         default:
786                                 why = "unknown reason";
787                                 break;
788                         }
789                         snprintf( c->msg, sizeof( c->msg),
790                                         "unable to parse uri \"%s\" "
791                                         "in \"uri <uri>\" line: %s",
792                                         c->value_string, why );
793                         Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
794                         urlrc = 1;
795                         goto done_url;
796                 }
797
798                 for ( i = 0, tmpludp = lud;
799                                 tmpludp;
800                                 i++, tmpludp = tmpludp->lud_next )
801                 {
802                         if ( ( tmpludp->lud_dn != NULL
803                                                 && tmpludp->lud_dn[0] != '\0' )
804                                         || tmpludp->lud_attrs != NULL
805                                         /* || tmpludp->lud_scope != LDAP_SCOPE_DEFAULT */
806                                         || tmpludp->lud_filter != NULL
807                                         || tmpludp->lud_exts != NULL )
808                         {
809                                 snprintf( c->msg, sizeof( c->msg ),
810                                                 "warning, only protocol, "
811                                                 "host and port allowed "
812                                                 "in \"uri <uri>\" statement "
813                                                 "for uri #%d of \"%s\"",
814                                                 i, c->value_string );
815                                 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
816                         }
817                 }
818
819                 for ( i = 0, tmpludp = lud;
820                                 tmpludp;
821                                 i++, tmpludp = tmpludp->lud_next )
822                         /* just count */
823                         ;
824                 urllist = ch_calloc( sizeof( char * ), i + 1 );
825
826                 for ( i = 0, tmpludp = lud;
827                                 tmpludp;
828                                 i++, tmpludp = tmpludp->lud_next )
829                 {
830                         LDAPURLDesc     tmplud;
831
832                         tmplud = *tmpludp;
833                         tmplud.lud_dn = "";
834                         tmplud.lud_attrs = NULL;
835                         tmplud.lud_filter = NULL;
836                         if ( !ldap_is_ldapi_url( tmplud.lud_scheme ) ) {
837                                 tmplud.lud_exts = NULL;
838                                 tmplud.lud_crit_exts = 0;
839                         }
840
841                         urllist[ i ]  = ldap_url_desc2str( &tmplud );
842
843                         if ( urllist[ i ] == NULL ) {
844                                 snprintf( c->msg, sizeof( c->msg),
845                                         "unable to rebuild uri "
846                                         "in \"uri <uri>\" statement "
847                                         "for \"%s\"",
848                                         c->argv[ 1 ] );
849                                 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
850                                 urlrc = 1;
851                                 goto done_url;
852                         }
853                 }
854
855                 li->li_uri = ldap_charray2str( urllist, " " );
856                 for ( i = 0; urllist[ i ] != NULL; i++ ) {
857                         struct berval   bv;
858
859                         ber_str2bv( urllist[ i ], 0, 0, &bv );
860                         ber_bvarray_add( &li->li_bvuri, &bv );
861                         urllist[ i ] = NULL;
862                 }
863                 ldap_memfree( urllist );
864                 urllist = NULL;
865
866 done_url:;
867                 if ( urllist ) {
868                         ldap_charray_free( urllist );
869                 }
870                 if ( lud ) {
871                         ldap_free_urllist( lud );
872                 }
873                 if ( urlrc != LDAP_URL_SUCCESS ) {
874                         return 1;
875                 }
876                 break;
877         }
878
879         case LDAP_BACK_CFG_TLS:
880                 i = verb_to_mask( c->argv[1], tls_mode );
881                 if ( BER_BVISNULL( &tls_mode[i].word ) ) {
882                         return 1;
883                 }
884                 li->li_flags &= ~LDAP_BACK_F_TLS_MASK;
885                 li->li_flags |= tls_mode[i].mask;
886                 break;
887
888         case LDAP_BACK_CFG_ACL_AUTHCDN:
889                 switch ( li->li_acl_authmethod ) {
890                 case LDAP_AUTH_NONE:
891                         li->li_acl_authmethod = LDAP_AUTH_SIMPLE;
892                         break;
893
894                 case LDAP_AUTH_SIMPLE:
895                         break;
896
897                 default:
898                         snprintf( c->msg, sizeof( c->msg),
899                                 "\"acl-authcDN <DN>\" incompatible "
900                                 "with auth method %d",
901                                 li->li_acl_authmethod );
902                         Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
903                         return 1;
904                 }
905                 if ( !BER_BVISNULL( &li->li_acl_authcDN ) ) {
906                         free( li->li_acl_authcDN.bv_val );
907                 }
908                 ber_memfree_x( c->value_dn.bv_val, NULL );
909                 li->li_acl_authcDN = c->value_ndn;
910                 BER_BVZERO( &c->value_dn );
911                 BER_BVZERO( &c->value_ndn );
912                 break;
913
914         case LDAP_BACK_CFG_ACL_PASSWD:
915                 switch ( li->li_acl_authmethod ) {
916                 case LDAP_AUTH_NONE:
917                         li->li_acl_authmethod = LDAP_AUTH_SIMPLE;
918                         break;
919
920                 case LDAP_AUTH_SIMPLE:
921                         break;
922
923                 default:
924                         snprintf( c->msg, sizeof( c->msg ),
925                                 "\"acl-passwd <cred>\" incompatible "
926                                 "with auth method %d",
927                                 li->li_acl_authmethod );
928                         Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
929                         return 1;
930                 }
931                 if ( !BER_BVISNULL( &li->li_acl_passwd ) ) {
932                         free( li->li_acl_passwd.bv_val );
933                 }
934                 ber_str2bv( c->argv[ 1 ], 0, 1, &li->li_acl_passwd );
935                 break;
936
937         case LDAP_BACK_CFG_ACL_METHOD:
938         case LDAP_BACK_CFG_ACL_BIND:
939                 for ( i = 1; i < c->argc; i++ ) {
940                         if ( bindconf_parse( c->argv[ i ], &li->li_acl ) ) {
941                                 return 1;
942                         }
943                 }
944                 break;
945
946         case LDAP_BACK_CFG_IDASSERT_MODE:
947                 i = verb_to_mask( c->argv[1], idassert_mode );
948                 if ( BER_BVISNULL( &idassert_mode[i].word ) ) {
949                         if ( strncasecmp( c->argv[1], "u:", STRLENOF( "u:" ) ) == 0 ) {
950                                 li->li_idassert_mode = LDAP_BACK_IDASSERT_OTHERID;
951                                 ber_str2bv( c->argv[1], 0, 1, &li->li_idassert_authzID );
952                                 li->li_idassert_authzID.bv_val[ 0 ] = 'u';
953                                 
954                         } else {
955                                 struct berval   id, ndn;
956
957                                 ber_str2bv( c->argv[1], 0, 0, &id );
958
959                                 if ( strncasecmp( c->argv[1], "dn:", STRLENOF( "dn:" ) ) == 0 ) {
960                                         id.bv_val += STRLENOF( "dn:" );
961                                         id.bv_len -= STRLENOF( "dn:" );
962                                 }
963
964                                 rc = dnNormalize( 0, NULL, NULL, &id, &ndn, NULL );
965                                 if ( rc != LDAP_SUCCESS ) {
966                                         Debug( LDAP_DEBUG_ANY,
967                                                 "%s: line %d: idassert ID \"%s\" is not a valid DN\n",
968                                                 c->fname, c->lineno, c->argv[1] );
969                                         return 1;
970                                 }
971
972                                 li->li_idassert_authzID.bv_len = STRLENOF( "dn:" ) + ndn.bv_len;
973                                 li->li_idassert_authzID.bv_val = ch_malloc( li->li_idassert_authzID.bv_len + 1 );
974                                 AC_MEMCPY( li->li_idassert_authzID.bv_val, "dn:", STRLENOF( "dn:" ) );
975                                 AC_MEMCPY( &li->li_idassert_authzID.bv_val[ STRLENOF( "dn:" ) ], ndn.bv_val, ndn.bv_len + 1 );
976                                 ch_free( ndn.bv_val );
977
978                                 li->li_idassert_mode = LDAP_BACK_IDASSERT_OTHERDN;
979                         }
980
981                 } else {
982                         li->li_idassert_mode = idassert_mode[i].mask;
983                 }
984
985                 if ( c->argc > 2 ) {
986                         int     i;
987
988                         for ( i = 2; i < c->argc; i++ ) {
989                                 if ( strcasecmp( c->argv[ i ], "override" ) == 0 ) {
990                                         li->li_idassert_flags |= LDAP_BACK_AUTH_OVERRIDE;
991
992                                 } else if ( strcasecmp( c->argv[ i ], "prescriptive" ) == 0 ) {
993                                         li->li_idassert_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
994
995                                 } else if ( strcasecmp( c->argv[ i ], "non-prescriptive" ) == 0 ) {
996                                         li->li_idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
997
998                                 } else if ( strcasecmp( c->argv[ i ], "obsolete-proxy-authz" ) == 0 ) {
999                                         if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
1000                                                 Debug( LDAP_DEBUG_ANY,
1001                                                         "%s: line %d: \"obsolete-proxy-authz\" flag "
1002                                                         "in \"idassert-mode <args>\" "
1003                                                         "incompatible with previously issued \"obsolete-encoding-workaround\" flag.\n",
1004                                                         c->fname, c->lineno, 0 );
1005                                                 return 1;
1006                                         }
1007                                         li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ;
1008
1009                                 } else if ( strcasecmp( c->argv[ i ], "obsolete-encoding-workaround" ) == 0 ) {
1010                                         if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
1011                                                 Debug( LDAP_DEBUG_ANY,
1012                                                         "%s: line %d: \"obsolete-encoding-workaround\" flag "
1013                                                         "in \"idassert-mode <args>\" "
1014                                                         "incompatible with previously issued \"obsolete-proxy-authz\" flag.\n",
1015                                                         c->fname, c->lineno, 0 );
1016                                                 return 1;
1017                                         }
1018                                         li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND;
1019
1020                                 } else {
1021                                         Debug( LDAP_DEBUG_ANY,
1022                                                 "%s: line %d: unknown flag #%d "
1023                                                 "in \"idassert-mode <args> "
1024                                                 "[<flags>]\" line.\n",
1025                                                 c->fname, c->lineno, i - 2 );
1026                                         return 1;
1027                                 }
1028                         }
1029                 }
1030                 break;
1031
1032         case LDAP_BACK_CFG_IDASSERT_AUTHCDN:
1033                 switch ( li->li_idassert_authmethod ) {
1034                 case LDAP_AUTH_NONE:
1035                         li->li_idassert_authmethod = LDAP_AUTH_SIMPLE;
1036                         break;
1037
1038                 case LDAP_AUTH_SIMPLE:
1039                         break;
1040
1041                 default:
1042                         snprintf( c->msg, sizeof( c->msg ),
1043                                 "\"idassert-authcDN <DN>\" incompatible "
1044                                 "with auth method %d",
1045                                 li->li_idassert_authmethod );
1046                         Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1047                         return 1;
1048                 }
1049                 if ( !BER_BVISNULL( &li->li_idassert_authcDN ) ) {
1050                         free( li->li_idassert_authcDN.bv_val );
1051                 }
1052                 ber_memfree_x( c->value_dn.bv_val, NULL );
1053                 li->li_idassert_authcDN = c->value_ndn;
1054                 BER_BVZERO( &c->value_dn );
1055                 BER_BVZERO( &c->value_ndn );
1056                 break;
1057
1058         case LDAP_BACK_CFG_IDASSERT_PASSWD:
1059                 switch ( li->li_idassert_authmethod ) {
1060                 case LDAP_AUTH_NONE:
1061                         li->li_idassert_authmethod = LDAP_AUTH_SIMPLE;
1062                         break;
1063
1064                 case LDAP_AUTH_SIMPLE:
1065                         break;
1066
1067                 default:
1068                         snprintf( c->msg, sizeof( c->msg ),
1069                                 "\"idassert-passwd <cred>\" incompatible "
1070                                 "with auth method %d",
1071                                 li->li_idassert_authmethod );
1072                         Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1073                         return 1;
1074                 }
1075                 if ( !BER_BVISNULL( &li->li_idassert_passwd ) ) {
1076                         free( li->li_idassert_passwd.bv_val );
1077                 }
1078                 ber_str2bv( c->argv[ 1 ], 0, 1, &li->li_idassert_passwd );
1079                 break;
1080
1081         case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
1082                 struct berval   bv;
1083                 struct berval   in;
1084                 int             rc;
1085
1086                 ber_str2bv( c->argv[ 1 ], 0, 0, &in );
1087                 rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL );
1088                 if ( rc != LDAP_SUCCESS ) {
1089                         snprintf( c->msg, sizeof( c->msg ),
1090                                 "\"idassert-authzFrom <authz>\": "
1091                                 "invalid syntax" );
1092                         Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1093                         return 1;
1094                 }
1095                 ber_bvarray_add( &li->li_idassert_authz, &bv );
1096                 } break;
1097
1098         case LDAP_BACK_CFG_IDASSERT_METHOD:
1099                 /* no longer supported */
1100                 snprintf( c->msg, sizeof( c->msg ),
1101                         "\"idassert-method <args>\": "
1102                         "no longer supported; use \"idassert-bind\"" );
1103                 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1104                 return 1;
1105
1106         case LDAP_BACK_CFG_IDASSERT_BIND:
1107                 for ( i = 1; i < c->argc; i++ ) {
1108                         if ( strncasecmp( c->argv[ i ], "mode=", STRLENOF( "mode=" ) ) == 0 ) {
1109                                 char    *argvi = c->argv[ i ] + STRLENOF( "mode=" );
1110                                 int     j;
1111
1112                                 j = verb_to_mask( argvi, idassert_mode );
1113                                 if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) {
1114                                         snprintf( c->msg, sizeof( c->msg ),
1115                                                 "\"idassert-bind <args>\": "
1116                                                 "unknown mode \"%s\"",
1117                                                 argvi );
1118                                         Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1119                                         return 1;
1120                                 }
1121
1122                                 li->li_idassert_mode = idassert_mode[ j ].mask;
1123
1124                         } else if ( strncasecmp( c->argv[ i ], "authz=", STRLENOF( "authz=" ) ) == 0 ) {
1125                                 char    *argvi = c->argv[ i ] + STRLENOF( "authz=" );
1126
1127                                 if ( strcasecmp( argvi, "native" ) == 0 ) {
1128                                         if ( li->li_idassert_authmethod != LDAP_AUTH_SASL ) {
1129                                                 snprintf( c->msg, sizeof( c->msg ),
1130                                                         "\"idassert-bind <args>\": "
1131                                                         "authz=\"native\" incompatible "
1132                                                         "with auth method" );
1133                                                 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1134                                                 return 1;
1135                                         }
1136                                         li->li_idassert_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
1137
1138                                 } else if ( strcasecmp( argvi, "proxyAuthz" ) == 0 ) {
1139                                         li->li_idassert_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
1140
1141                                 } else {
1142                                         snprintf( c->msg, sizeof( c->msg ),
1143                                                 "\"idassert-bind <args>\": "
1144                                                 "unknown authz \"%s\"",
1145                                                 argvi );
1146                                         Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1147                                         return 1;
1148                                 }
1149
1150                         } else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) {
1151                                 char    *argvi = c->argv[ i ] + STRLENOF( "flags=" );
1152                                 char    **flags = ldap_str2charray( argvi, "," );
1153                                 int     j;
1154
1155                                 if ( flags == NULL ) {
1156                                         snprintf( c->msg, sizeof( c->msg ),
1157                                                 "\"idassert-bind <args>\": "
1158                                                 "unable to parse flags \"%s\"",
1159                                                 argvi );
1160                                         Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1161                                         return 1;
1162                                 }
1163
1164                                 for ( j = 0; flags[ j ] != NULL; j++ ) {
1165                                         if ( strcasecmp( flags[ j ], "override" ) == 0 ) {
1166                                                 li->li_idassert_flags |= LDAP_BACK_AUTH_OVERRIDE;
1167
1168                                         } else if ( strcasecmp( flags[ j ], "prescriptive" ) == 0 ) {
1169                                                 li->li_idassert_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
1170
1171                                         } else if ( strcasecmp( flags[ j ], "non-prescriptive" ) == 0 ) {
1172                                                 li->li_idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
1173
1174                                         } else if ( strcasecmp( flags[ j ], "obsolete-proxy-authz" ) == 0 ) {
1175                                                 if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
1176                                                         Debug( LDAP_DEBUG_ANY,
1177                                                                 "%s: line %d: \"obsolete-proxy-authz\" flag "
1178                                                                 "in \"idassert-mode <args>\" "
1179                                                                 "incompatible with previously issued \"obsolete-encoding-workaround\" flag.\n",
1180                                                                 c->fname, c->lineno, 0 );
1181                                                         return 1;
1182                                                 }
1183                                                 li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ;
1184
1185                                         } else if ( strcasecmp( flags[ j ], "obsolete-encoding-workaround" ) == 0 ) {
1186                                                 if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
1187                                                         Debug( LDAP_DEBUG_ANY,
1188                                                                 "%s: line %d: \"obsolete-encoding-workaround\" flag "
1189                                                                 "in \"idassert-mode <args>\" "
1190                                                                 "incompatible with previously issued \"obsolete-proxy-authz\" flag.\n",
1191                                                                 c->fname, c->lineno, 0 );
1192                                                         return 1;
1193                                                 }
1194                                                 li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND;
1195
1196                                         } else {
1197                                                 snprintf( c->msg, sizeof( c->msg ),
1198                                                         "\"idassert-bind <args>\": "
1199                                                         "unknown flag \"%s\"",
1200                                                         flags[ j ] );
1201                                                 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1202                                                 ldap_charray_free( flags );
1203                                                 return 1;
1204                                         }
1205                                 }
1206
1207                                 ldap_charray_free( flags );
1208
1209                         } else if ( bindconf_parse( c->argv[ i ], &li->li_idassert ) ) {
1210                                 return 1;
1211                         }
1212                 }
1213                 break;
1214
1215         case LDAP_BACK_CFG_REBIND:
1216                 if ( c->argc == 1 || c->value_int ) {
1217                         li->li_flags |= LDAP_BACK_F_SAVECRED;
1218
1219                 } else {
1220                         li->li_flags &= ~LDAP_BACK_F_SAVECRED;
1221                 }
1222                 break;
1223
1224         case LDAP_BACK_CFG_CHASE:
1225                 if ( c->argc == 1 || c->value_int ) {
1226                         li->li_flags |= LDAP_BACK_F_CHASE_REFERRALS;
1227
1228                 } else {
1229                         li->li_flags &= ~LDAP_BACK_F_CHASE_REFERRALS;
1230                 }
1231                 break;
1232
1233         case LDAP_BACK_CFG_T_F:
1234                 i = verb_to_mask( c->argv[1], t_f_mode );
1235                 if ( BER_BVISNULL( &t_f_mode[i].word ) ) {
1236                         return 1;
1237                 }
1238                 li->li_flags &= ~LDAP_BACK_F_SUPPORT_T_F_MASK;
1239                 li->li_flags |= t_f_mode[i].mask;
1240                 break;
1241
1242         case LDAP_BACK_CFG_WHOAMI:
1243                 if ( c->argc == 1 || c->value_int ) {
1244                         li->li_flags |= LDAP_BACK_F_PROXY_WHOAMI;
1245                         load_extop( (struct berval *)&slap_EXOP_WHOAMI,
1246                                         0, ldap_back_exop_whoami );
1247
1248                 } else {
1249                         li->li_flags &= ~LDAP_BACK_F_PROXY_WHOAMI;
1250                 }
1251                 break;
1252
1253         case LDAP_BACK_CFG_TIMEOUT:
1254                 for ( i = 1; i < c->argc; i++ ) {
1255                         if ( isdigit( (unsigned char) c->argv[ i ][ 0 ] ) ) {
1256                                 int             j;
1257                                 unsigned        u;
1258
1259                                 if ( lutil_atoux( &u, c->argv[ i ], 0 ) != 0 ) {
1260                                         return 1;
1261                                 }
1262
1263                                 for ( j = 0; j < LDAP_BACK_OP_LAST; j++ ) {
1264                                         li->li_timeout[ j ] = u;
1265                                 }
1266
1267                                 continue;
1268                         }
1269
1270                         if ( slap_cf_aux_table_parse( c->argv[ i ], li->li_timeout, timeout_table, "slapd-ldap timeout" ) ) {
1271                                 return 1;
1272                         }
1273                 }
1274                 break;
1275
1276         case LDAP_BACK_CFG_IDLE_TIMEOUT: {
1277                 unsigned long   t;
1278
1279                 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
1280                         snprintf( c->msg, sizeof( c->msg),
1281                                 "unable to parse idle timeout \"%s\"",
1282                                 c->argv[ 1 ] );
1283                         Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1284                         return 1;
1285                 }
1286                 li->li_idle_timeout = (time_t)t;
1287                 } break;
1288
1289         case LDAP_BACK_CFG_CONN_TTL: {
1290                 unsigned long   t;
1291
1292                 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
1293                         snprintf( c->msg, sizeof( c->msg),
1294                                 "unable to parse conn ttl\"%s\"",
1295                                 c->argv[ 1 ] );
1296                         Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1297                         return 1;
1298                 }
1299                 li->li_conn_ttl = (time_t)t;
1300                 } break;
1301
1302         case LDAP_BACK_CFG_NETWORK_TIMEOUT: {
1303                 unsigned long   t;
1304
1305                 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
1306                         snprintf( c->msg, sizeof( c->msg),
1307                                 "unable to parse network timeout \"%s\"",
1308                                 c->argv[ 1 ] );
1309                         Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1310                         return 1;
1311                 }
1312                 li->li_network_timeout = (time_t)t;
1313                 } break;
1314
1315         case LDAP_BACK_CFG_VERSION:
1316                 switch ( c->value_int ) {
1317                 case 0:
1318                 case LDAP_VERSION2:
1319                 case LDAP_VERSION3:
1320                         li->li_version = c->value_int;
1321                         break;
1322
1323                 default:
1324                         return 1;
1325                 }
1326                 break;
1327
1328         case LDAP_BACK_CFG_REWRITE:
1329                 snprintf( c->msg, sizeof( c->msg ),
1330                         "rewrite/remap capabilities have been moved "
1331                         "to the \"rwm\" overlay; see slapo-rwm(5) "
1332                         "for details (hint: add \"overlay rwm\" "
1333                         "and prefix all directives with \"rwm-\")" );
1334                 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
1335                 return 1;
1336                 
1337         default:
1338                 /* FIXME: try to catch inconsistencies */
1339                 assert( 0 );
1340                 break;
1341         }
1342
1343         return 0;
1344 }
1345
1346 int
1347 ldap_back_init_cf( BackendInfo *bi )
1348 {
1349         int                     rc;
1350         AttributeDescription    *ad = NULL;
1351         const char              *text;
1352
1353         /* Make sure we don't exceed the bits reserved for userland */
1354         config_check_userland( LDAP_BACK_CFG_LAST );
1355
1356         bi->bi_cf_ocs = ldapocs;
1357
1358         rc = config_register_schema( ldapcfg, ldapocs );
1359         if ( rc ) {
1360                 return rc;
1361         }
1362
1363         /* setup olcDbAclPasswd and olcDbIDAssertPasswd 
1364          * to be base64-encoded when written in LDIF form;
1365          * basically, we don't care if it fails */
1366         rc = slap_str2ad( "olcDbACLPasswd", &ad, &text );
1367         if ( rc ) {
1368                 Debug( LDAP_DEBUG_ANY, "config_back_initialize: "
1369                         "warning, unable to get \"olcDbACLPasswd\" "
1370                         "attribute description: %d: %s\n",
1371                         rc, text, 0 );
1372         } else {
1373                 (void)ldif_must_b64_encode_register( ad->ad_cname.bv_val,
1374                         ad->ad_type->sat_oid );
1375         }
1376
1377         ad = NULL;
1378         rc = slap_str2ad( "olcDbIDAssertPasswd", &ad, &text );
1379         if ( rc ) {
1380                 Debug( LDAP_DEBUG_ANY, "config_back_initialize: "
1381                         "warning, unable to get \"olcDbIDAssertPasswd\" "
1382                         "attribute description: %d: %s\n",
1383                         rc, text, 0 );
1384         } else {
1385                 (void)ldif_must_b64_encode_register( ad->ad_cname.bv_val,
1386                         ad->ad_type->sat_oid );
1387         }
1388
1389         return 0;
1390 }
1391
1392
1393 static int
1394 ldap_back_exop_whoami(
1395                 Operation       *op,
1396                 SlapReply       *rs )
1397 {
1398         struct berval *bv = NULL;
1399
1400         if ( op->oq_extended.rs_reqdata != NULL ) {
1401                 /* no request data should be provided */
1402                 rs->sr_text = "no request data expected";
1403                 return rs->sr_err = LDAP_PROTOCOL_ERROR;
1404         }
1405
1406         Statslog( LDAP_DEBUG_STATS, "%s WHOAMI\n",
1407             op->o_log_prefix, 0, 0, 0, 0 );
1408
1409         rs->sr_err = backend_check_restrictions( op, rs, 
1410                         (struct berval *)&slap_EXOP_WHOAMI );
1411         if( rs->sr_err != LDAP_SUCCESS ) return rs->sr_err;
1412
1413         /* if auth'd by back-ldap and request is proxied, forward it */
1414         if ( op->o_conn->c_authz_backend
1415                 && !strcmp( op->o_conn->c_authz_backend->be_type, "ldap" )
1416                 && !dn_match( &op->o_ndn, &op->o_conn->c_ndn ) )
1417         {
1418                 ldapconn_t      *lc;
1419                 LDAPControl c, *ctrls[2] = {NULL, NULL};
1420                 LDAPMessage *res;
1421                 Operation op2 = *op;
1422                 ber_int_t msgid;
1423                 int doretry = 1;
1424                 char *ptr;
1425
1426                 ctrls[0] = &c;
1427                 op2.o_ndn = op->o_conn->c_ndn;
1428                 lc = ldap_back_getconn(&op2, rs, LDAP_BACK_SENDERR);
1429                 if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
1430                         return -1;
1431                 }
1432                 c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
1433                 c.ldctl_iscritical = 1;
1434                 c.ldctl_value.bv_val = op->o_tmpalloc(
1435                         op->o_ndn.bv_len + STRLENOF( "dn:" ) + 1,
1436                         op->o_tmpmemctx );
1437                 c.ldctl_value.bv_len = op->o_ndn.bv_len + 3;
1438                 ptr = c.ldctl_value.bv_val;
1439                 ptr = lutil_strcopy( ptr, "dn:" );
1440                 ptr = lutil_strncopy( ptr, op->o_ndn.bv_val, op->o_ndn.bv_len );
1441                 ptr[ 0 ] = '\0';
1442
1443 retry:
1444                 rs->sr_err = ldap_whoami( lc->lc_ld, ctrls, NULL, &msgid );
1445                 if ( rs->sr_err == LDAP_SUCCESS ) {
1446                         if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, NULL, &res ) == -1 ) {
1447                                 ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER,
1448                                         &rs->sr_err );
1449                                 if ( rs->sr_err == LDAP_SERVER_DOWN && doretry ) {
1450                                         doretry = 0;
1451                                         if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
1452                                                 goto retry;
1453                                         }
1454                                 }
1455
1456                         } else {
1457                                 /* NOTE: are we sure "bv" will be malloc'ed
1458                                  * with the appropriate memory? */
1459                                 rs->sr_err = ldap_parse_whoami( lc->lc_ld, res, &bv );
1460                                 ldap_msgfree(res);
1461                         }
1462                 }
1463                 op->o_tmpfree( c.ldctl_value.bv_val, op->o_tmpmemctx );
1464                 if ( rs->sr_err != LDAP_SUCCESS ) {
1465                         rs->sr_err = slap_map_api2result( rs );
1466                 }
1467
1468                 if ( lc != NULL ) {
1469                         ldap_back_release_conn( &op2, rs, lc );
1470                 }
1471
1472         } else {
1473                 /* else just do the same as before */
1474                 bv = (struct berval *) ch_malloc( sizeof( struct berval ) );
1475                 if ( !BER_BVISEMPTY( &op->o_dn ) ) {
1476                         bv->bv_len = op->o_dn.bv_len + STRLENOF( "dn:" );
1477                         bv->bv_val = ch_malloc( bv->bv_len + 1 );
1478                         AC_MEMCPY( bv->bv_val, "dn:", STRLENOF( "dn:" ) );
1479                         AC_MEMCPY( &bv->bv_val[ STRLENOF( "dn:" ) ], op->o_dn.bv_val,
1480                                 op->o_dn.bv_len );
1481                         bv->bv_val[ bv->bv_len ] = '\0';
1482
1483                 } else {
1484                         bv->bv_len = 0;
1485                         bv->bv_val = NULL;
1486                 }
1487         }
1488
1489         rs->sr_rspdata = bv;
1490         return rs->sr_err;
1491 }
1492
1493