xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-ldap/config.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: config.c,v 1.1.1.4 2010/12/12 15:23:05 adam Exp $	*/
2 
3 /* config.c - ldap backend configuration file routine */
4 /* OpenLDAP: pkg/ldap/servers/slapd/back-ldap/config.c,v 1.115.2.23 2010/04/19 19:28:15 quanah Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2003-2010 The OpenLDAP Foundation.
8  * Portions Copyright 1999-2003 Howard Chu.
9  * Portions Copyright 2000-2003 Pierangelo Masarati.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted only as authorized by the OpenLDAP
14  * Public License.
15  *
16  * A copy of this license is available in the file LICENSE in the
17  * top-level directory of the distribution or, alternatively, at
18  * <http://www.OpenLDAP.org/license.html>.
19  */
20 /* ACKNOWLEDGEMENTS:
21  * This work was initially developed by the Howard Chu for inclusion
22  * in OpenLDAP Software and subsequently enhanced by Pierangelo
23  * Masarati.
24  */
25 
26 #include "portable.h"
27 
28 #include <stdio.h>
29 
30 #include <ac/string.h>
31 #include <ac/ctype.h>
32 #include <ac/socket.h>
33 
34 #include "slap.h"
35 #include "config.h"
36 #include "back-ldap.h"
37 #include "lutil.h"
38 #include "ldif.h"
39 #undef ldap_debug
40 /* for advanced URL parsing */
41 #include "../../../libraries/libldap/ldap-int.h"
42 
43 static SLAP_EXTOP_MAIN_FN ldap_back_exop_whoami;
44 
45 static ConfigDriver ldap_back_cf_gen;
46 static ConfigDriver ldap_pbind_cf_gen;
47 
48 enum {
49 	LDAP_BACK_CFG_URI = 1,
50 	LDAP_BACK_CFG_TLS,
51 	LDAP_BACK_CFG_ACL_AUTHCDN,
52 	LDAP_BACK_CFG_ACL_PASSWD,
53 	LDAP_BACK_CFG_ACL_METHOD,
54 	LDAP_BACK_CFG_ACL_BIND,
55 	LDAP_BACK_CFG_IDASSERT_MODE,
56 	LDAP_BACK_CFG_IDASSERT_AUTHCDN,
57 	LDAP_BACK_CFG_IDASSERT_PASSWD,
58 	LDAP_BACK_CFG_IDASSERT_AUTHZFROM,
59 	LDAP_BACK_CFG_IDASSERT_PASSTHRU,
60 	LDAP_BACK_CFG_IDASSERT_METHOD,
61 	LDAP_BACK_CFG_IDASSERT_BIND,
62 	LDAP_BACK_CFG_REBIND,
63 	LDAP_BACK_CFG_CHASE,
64 	LDAP_BACK_CFG_T_F,
65 	LDAP_BACK_CFG_WHOAMI,
66 	LDAP_BACK_CFG_TIMEOUT,
67 	LDAP_BACK_CFG_IDLE_TIMEOUT,
68 	LDAP_BACK_CFG_CONN_TTL,
69 	LDAP_BACK_CFG_NETWORK_TIMEOUT,
70 	LDAP_BACK_CFG_VERSION,
71 	LDAP_BACK_CFG_SINGLECONN,
72 	LDAP_BACK_CFG_USETEMP,
73 	LDAP_BACK_CFG_CONNPOOLMAX,
74 	LDAP_BACK_CFG_CANCEL,
75 	LDAP_BACK_CFG_QUARANTINE,
76 	LDAP_BACK_CFG_ST_REQUEST,
77 	LDAP_BACK_CFG_NOREFS,
78 	LDAP_BACK_CFG_NOUNDEFFILTER,
79 
80 	LDAP_BACK_CFG_REWRITE,
81 
82 	LDAP_BACK_CFG_LAST
83 };
84 
85 static ConfigTable ldapcfg[] = {
86 	{ "uri", "uri", 2, 2, 0,
87 		ARG_MAGIC|LDAP_BACK_CFG_URI,
88 		ldap_back_cf_gen, "( OLcfgDbAt:0.14 "
89 			"NAME 'olcDbURI' "
90 			"DESC 'URI (list) for remote DSA' "
91 			"SYNTAX OMsDirectoryString "
92 			"SINGLE-VALUE )",
93 		NULL, NULL },
94 	{ "tls", "what", 2, 0, 0,
95 		ARG_MAGIC|LDAP_BACK_CFG_TLS,
96 		ldap_back_cf_gen, "( OLcfgDbAt:3.1 "
97 			"NAME 'olcDbStartTLS' "
98 			"DESC 'StartTLS' "
99 			"SYNTAX OMsDirectoryString "
100 			"SINGLE-VALUE )",
101 		NULL, NULL },
102 	{ "acl-authcDN", "DN", 2, 2, 0,
103 		ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_ACL_AUTHCDN,
104 		ldap_back_cf_gen, "( OLcfgDbAt:3.2 "
105 			"NAME 'olcDbACLAuthcDn' "
106 			"DESC 'Remote ACL administrative identity' "
107 			"OBSOLETE "
108 			"SYNTAX OMsDN "
109 			"SINGLE-VALUE )",
110 		NULL, NULL },
111 	/* deprecated, will be removed; aliases "acl-authcDN" */
112 	{ "binddn", "DN", 2, 2, 0,
113 		ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_ACL_AUTHCDN,
114 		ldap_back_cf_gen, NULL, NULL, NULL },
115 	{ "acl-passwd", "cred", 2, 2, 0,
116 		ARG_MAGIC|LDAP_BACK_CFG_ACL_PASSWD,
117 		ldap_back_cf_gen, "( OLcfgDbAt:3.3 "
118 			"NAME 'olcDbACLPasswd' "
119 			"DESC 'Remote ACL administrative identity credentials' "
120 			"OBSOLETE "
121 			"SYNTAX OMsDirectoryString "
122 			"SINGLE-VALUE )",
123 		NULL, NULL },
124 	/* deprecated, will be removed; aliases "acl-passwd" */
125 	{ "bindpw", "cred", 2, 2, 0,
126 		ARG_MAGIC|LDAP_BACK_CFG_ACL_PASSWD,
127 		ldap_back_cf_gen, NULL, NULL, NULL },
128 	/* deprecated, will be removed; aliases "acl-bind" */
129 	{ "acl-method", "args", 2, 0, 0,
130 		ARG_MAGIC|LDAP_BACK_CFG_ACL_METHOD,
131 		ldap_back_cf_gen, NULL, NULL, NULL },
132 	{ "acl-bind", "args", 2, 0, 0,
133 		ARG_MAGIC|LDAP_BACK_CFG_ACL_BIND,
134 		ldap_back_cf_gen, "( OLcfgDbAt:3.4 "
135 			"NAME 'olcDbACLBind' "
136 			"DESC 'Remote ACL administrative identity auth bind configuration' "
137 			"SYNTAX OMsDirectoryString "
138 			"SINGLE-VALUE )",
139 		NULL, NULL },
140 	{ "idassert-authcDN", "DN", 2, 2, 0,
141 		ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHCDN,
142 		ldap_back_cf_gen, "( OLcfgDbAt:3.5 "
143 			"NAME 'olcDbIDAssertAuthcDn' "
144 			"DESC 'Remote Identity Assertion administrative identity' "
145 			"OBSOLETE "
146 			"SYNTAX OMsDN "
147 			"SINGLE-VALUE )",
148 		NULL, NULL },
149 	/* deprecated, will be removed; partially aliases "idassert-authcDN" */
150 	{ "proxyauthzdn", "DN", 2, 2, 0,
151 		ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHCDN,
152 		ldap_back_cf_gen, NULL, NULL, NULL },
153 	{ "idassert-passwd", "cred", 2, 2, 0,
154 		ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_PASSWD,
155 		ldap_back_cf_gen, "( OLcfgDbAt:3.6 "
156 			"NAME 'olcDbIDAssertPasswd' "
157 			"DESC 'Remote Identity Assertion administrative identity credentials' "
158 			"OBSOLETE "
159 			"SYNTAX OMsDirectoryString "
160 			"SINGLE-VALUE )",
161 		NULL, NULL },
162 	/* deprecated, will be removed; partially aliases "idassert-passwd" */
163 	{ "proxyauthzpw", "cred", 2, 2, 0,
164 		ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_PASSWD,
165 		ldap_back_cf_gen, NULL, NULL, NULL },
166 	{ "idassert-bind", "args", 2, 0, 0,
167 		ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND,
168 		ldap_back_cf_gen, "( OLcfgDbAt:3.7 "
169 			"NAME 'olcDbIDAssertBind' "
170 			"DESC 'Remote Identity Assertion administrative identity auth bind configuration' "
171 			"SYNTAX OMsDirectoryString "
172 			"SINGLE-VALUE )",
173 		NULL, NULL },
174 	{ "idassert-method", "args", 2, 0, 0,
175 		ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_METHOD,
176 		ldap_back_cf_gen, NULL, NULL, NULL },
177 	{ "idassert-mode", "mode>|u:<user>|[dn:]<DN", 2, 0, 0,
178 		ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_MODE,
179 		ldap_back_cf_gen, "( OLcfgDbAt:3.8 "
180 			"NAME 'olcDbIDAssertMode' "
181 			"DESC 'Remote Identity Assertion mode' "
182 			"OBSOLETE "
183 			"SYNTAX OMsDirectoryString "
184 			"SINGLE-VALUE)",
185 		NULL, NULL },
186 	{ "idassert-authzFrom", "authzRule", 2, 2, 0,
187 		ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHZFROM,
188 		ldap_back_cf_gen, "( OLcfgDbAt:3.9 "
189 			"NAME 'olcDbIDAssertAuthzFrom' "
190 			"DESC 'Remote Identity Assertion authz rules' "
191 			"EQUALITY caseIgnoreMatch "
192 			"SYNTAX OMsDirectoryString "
193 			"X-ORDERED 'VALUES' )",
194 		NULL, NULL },
195 	{ "rebind-as-user", "true|FALSE", 1, 2, 0,
196 		ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND,
197 		ldap_back_cf_gen, "( OLcfgDbAt:3.10 "
198 			"NAME 'olcDbRebindAsUser' "
199 			"DESC 'Rebind as user' "
200 			"SYNTAX OMsBoolean "
201 			"SINGLE-VALUE )",
202 		NULL, NULL },
203 	{ "chase-referrals", "true|FALSE", 2, 2, 0,
204 		ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE,
205 		ldap_back_cf_gen, "( OLcfgDbAt:3.11 "
206 			"NAME 'olcDbChaseReferrals' "
207 			"DESC 'Chase referrals' "
208 			"SYNTAX OMsBoolean "
209 			"SINGLE-VALUE )",
210 		NULL, NULL },
211 	{ "t-f-support", "true|FALSE|discover", 2, 2, 0,
212 		ARG_MAGIC|LDAP_BACK_CFG_T_F,
213 		ldap_back_cf_gen, "( OLcfgDbAt:3.12 "
214 			"NAME 'olcDbTFSupport' "
215 			"DESC 'Absolute filters support' "
216 			"SYNTAX OMsDirectoryString "
217 			"SINGLE-VALUE )",
218 		NULL, NULL },
219 	{ "proxy-whoami", "true|FALSE", 1, 2, 0,
220 		ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_WHOAMI,
221 		ldap_back_cf_gen, "( OLcfgDbAt:3.13 "
222 			"NAME 'olcDbProxyWhoAmI' "
223 			"DESC 'Proxy whoAmI exop' "
224 			"SYNTAX OMsBoolean "
225 			"SINGLE-VALUE )",
226 		NULL, NULL },
227 	{ "timeout", "timeout(list)", 2, 0, 0,
228 		ARG_MAGIC|LDAP_BACK_CFG_TIMEOUT,
229 		ldap_back_cf_gen, "( OLcfgDbAt:3.14 "
230 			"NAME 'olcDbTimeout' "
231 			"DESC 'Per-operation timeouts' "
232 			"SYNTAX OMsDirectoryString "
233 			"SINGLE-VALUE )",
234 		NULL, NULL },
235 	{ "idle-timeout", "timeout", 2, 2, 0,
236 		ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT,
237 		ldap_back_cf_gen, "( OLcfgDbAt:3.15 "
238 			"NAME 'olcDbIdleTimeout' "
239 			"DESC 'connection idle timeout' "
240 			"SYNTAX OMsDirectoryString "
241 			"SINGLE-VALUE )",
242 		NULL, NULL },
243 	{ "conn-ttl", "ttl", 2, 2, 0,
244 		ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL,
245 		ldap_back_cf_gen, "( OLcfgDbAt:3.16 "
246 			"NAME 'olcDbConnTtl' "
247 			"DESC 'connection ttl' "
248 			"SYNTAX OMsDirectoryString "
249 			"SINGLE-VALUE )",
250 		NULL, NULL },
251 	{ "network-timeout", "timeout", 2, 2, 0,
252 		ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT,
253 		ldap_back_cf_gen, "( OLcfgDbAt:3.17 "
254 			"NAME 'olcDbNetworkTimeout' "
255 			"DESC 'connection network timeout' "
256 			"SYNTAX OMsDirectoryString "
257 			"SINGLE-VALUE )",
258 		NULL, NULL },
259 	{ "protocol-version", "version", 2, 2, 0,
260 		ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION,
261 		ldap_back_cf_gen, "( OLcfgDbAt:3.18 "
262 			"NAME 'olcDbProtocolVersion' "
263 			"DESC 'protocol version' "
264 			"SYNTAX OMsInteger "
265 			"SINGLE-VALUE )",
266 		NULL, NULL },
267 	{ "single-conn", "true|FALSE", 2, 2, 0,
268 		ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN,
269 		ldap_back_cf_gen, "( OLcfgDbAt:3.19 "
270 			"NAME 'olcDbSingleConn' "
271 			"DESC 'cache a single connection per identity' "
272 			"SYNTAX OMsBoolean "
273 			"SINGLE-VALUE )",
274 		NULL, NULL },
275 	{ "cancel", "ABANDON|ignore|exop", 2, 2, 0,
276 		ARG_MAGIC|LDAP_BACK_CFG_CANCEL,
277 		ldap_back_cf_gen, "( OLcfgDbAt:3.20 "
278 			"NAME 'olcDbCancel' "
279 			"DESC 'abandon/ignore/exop operations when appropriate' "
280 			"SYNTAX OMsDirectoryString "
281 			"SINGLE-VALUE )",
282 		NULL, NULL },
283 	{ "quarantine", "retrylist", 2, 2, 0,
284 		ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE,
285 		ldap_back_cf_gen, "( OLcfgDbAt:3.21 "
286 			"NAME 'olcDbQuarantine' "
287 			"DESC 'Quarantine database if connection fails and retry according to rule' "
288 			"SYNTAX OMsDirectoryString "
289 			"SINGLE-VALUE )",
290 		NULL, NULL },
291 	{ "use-temporary-conn", "true|FALSE", 2, 2, 0,
292 		ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_USETEMP,
293 		ldap_back_cf_gen, "( OLcfgDbAt:3.22 "
294 			"NAME 'olcDbUseTemporaryConn' "
295 			"DESC 'Use temporary connections if the cached one is busy' "
296 			"SYNTAX OMsBoolean "
297 			"SINGLE-VALUE )",
298 		NULL, NULL },
299 	{ "conn-pool-max", "<n>", 2, 2, 0,
300 		ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX,
301 		ldap_back_cf_gen, "( OLcfgDbAt:3.23 "
302 			"NAME 'olcDbConnectionPoolMax' "
303 			"DESC 'Max size of privileged connections pool' "
304 			"SYNTAX OMsInteger "
305 			"SINGLE-VALUE )",
306 		NULL, NULL },
307 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
308 	{ "session-tracking-request", "true|FALSE", 2, 2, 0,
309 		ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_ST_REQUEST,
310 		ldap_back_cf_gen, "( OLcfgDbAt:3.24 "
311 			"NAME 'olcDbSessionTrackingRequest' "
312 			"DESC 'Add session tracking control to proxied requests' "
313 			"SYNTAX OMsBoolean "
314 			"SINGLE-VALUE )",
315 		NULL, NULL },
316 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
317 	{ "norefs", "true|FALSE", 2, 2, 0,
318 		ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOREFS,
319 		ldap_back_cf_gen, "( OLcfgDbAt:3.25 "
320 			"NAME 'olcDbNoRefs' "
321 			"DESC 'Do not return search reference responses' "
322 			"SYNTAX OMsBoolean "
323 			"SINGLE-VALUE )",
324 		NULL, NULL },
325 	{ "noundeffilter", "true|FALSE", 2, 2, 0,
326 		ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOUNDEFFILTER,
327 		ldap_back_cf_gen, "( OLcfgDbAt:3.26 "
328 			"NAME 'olcDbNoUndefFilter' "
329 			"DESC 'Do not propagate undefined search filters' "
330 			"SYNTAX OMsBoolean "
331 			"SINGLE-VALUE )",
332 		NULL, NULL },
333 	{ "idassert-passThru", "authzRule", 2, 2, 0,
334 		ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_PASSTHRU,
335 		ldap_back_cf_gen, "( OLcfgDbAt:3.27 "
336 			"NAME 'olcDbIDAssertPassThru' "
337 			"DESC 'Remote Identity Assertion passthru rules' "
338 			"EQUALITY caseIgnoreMatch "
339 			"SYNTAX OMsDirectoryString "
340 			"X-ORDERED 'VALUES' )",
341 		NULL, NULL },
342 
343 	{ "suffixmassage", "[virtual]> <real", 2, 3, 0,
344 		ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
345 		ldap_back_cf_gen, NULL, NULL, NULL },
346 	{ "map", "attribute|objectClass> [*|<local>] *|<remote", 3, 4, 0,
347 		ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
348 		ldap_back_cf_gen, NULL, NULL, NULL },
349 	{ "rewrite", "<arglist>", 2, 4, STRLENOF( "rewrite" ),
350 		ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
351 		ldap_back_cf_gen, NULL, NULL, NULL },
352 	{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
353 		NULL, NULL, NULL, NULL }
354 };
355 
356 static ConfigOCs ldapocs[] = {
357 	{ "( OLcfgDbOc:3.1 "
358 		"NAME 'olcLDAPConfig' "
359 		"DESC 'LDAP backend configuration' "
360 		"SUP olcDatabaseConfig "
361 		"MAY ( olcDbURI "
362 			"$ olcDbStartTLS "
363 			"$ olcDbACLAuthcDn "
364 			"$ olcDbACLPasswd "
365 			"$ olcDbACLBind "
366 			"$ olcDbIDAssertAuthcDn "
367 			"$ olcDbIDAssertPasswd "
368 			"$ olcDbIDAssertBind "
369 			"$ olcDbIDAssertMode "
370 			"$ olcDbIDAssertAuthzFrom "
371 			"$ olcDbIDAssertPassThru "
372 			"$ olcDbRebindAsUser "
373 			"$ olcDbChaseReferrals "
374 			"$ olcDbTFSupport "
375 			"$ olcDbProxyWhoAmI "
376 			"$ olcDbTimeout "
377 			"$ olcDbIdleTimeout "
378 			"$ olcDbConnTtl "
379 			"$ olcDbNetworkTimeout "
380 			"$ olcDbProtocolVersion "
381 			"$ olcDbSingleConn "
382 			"$ olcDbCancel "
383 			"$ olcDbQuarantine "
384 			"$ olcDbUseTemporaryConn "
385 			"$ olcDbConnectionPoolMax "
386 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
387 			"$ olcDbSessionTrackingRequest "
388 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
389 			"$ olcDbNoRefs "
390 			"$ olcDbNoUndefFilter "
391 		") )",
392 		 	Cft_Database, ldapcfg},
393 	{ NULL, 0, NULL }
394 };
395 
396 static ConfigTable pbindcfg[] = {
397 	{ "uri", "uri", 2, 2, 0,
398 		ARG_MAGIC|LDAP_BACK_CFG_URI,
399 		ldap_pbind_cf_gen, "( OLcfgDbAt:0.14 "
400 			"NAME 'olcDbURI' "
401 			"DESC 'URI (list) for remote DSA' "
402 			"SYNTAX OMsDirectoryString "
403 			"SINGLE-VALUE )",
404 		NULL, NULL },
405 	{ "tls", "what", 2, 0, 0,
406 		ARG_MAGIC|LDAP_BACK_CFG_TLS,
407 		ldap_pbind_cf_gen, "( OLcfgDbAt:3.1 "
408 			"NAME 'olcDbStartTLS' "
409 			"DESC 'StartTLS' "
410 			"SYNTAX OMsDirectoryString "
411 			"SINGLE-VALUE )",
412 		NULL, NULL },
413 	{ "network-timeout", "timeout", 2, 2, 0,
414 		ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT,
415 		ldap_pbind_cf_gen, "( OLcfgDbAt:3.17 "
416 			"NAME 'olcDbNetworkTimeout' "
417 			"DESC 'connection network timeout' "
418 			"SYNTAX OMsDirectoryString "
419 			"SINGLE-VALUE )",
420 		NULL, NULL },
421 	{ "quarantine", "retrylist", 2, 2, 0,
422 		ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE,
423 		ldap_pbind_cf_gen, "( OLcfgDbAt:3.21 "
424 			"NAME 'olcDbQuarantine' "
425 			"DESC 'Quarantine database if connection fails and retry according to rule' "
426 			"SYNTAX OMsDirectoryString "
427 			"SINGLE-VALUE )",
428 		NULL, NULL },
429 	{ NULL, NULL, 0, 0, 0, ARG_IGNORED,
430 		NULL, NULL, NULL, NULL }
431 };
432 
433 static ConfigOCs pbindocs[] = {
434 	{ "( OLcfgOvOc:3.3 "
435 		"NAME 'olcPBindConfig' "
436 		"DESC 'Proxy Bind configuration' "
437 		"SUP olcOverlayConfig "
438 		"MUST olcDbURI "
439 		"MAY ( olcDbStartTLS "
440 			"$ olcDbNetworkTimeout "
441 			"$ olcDbQuarantine "
442 		") )",
443 		 	Cft_Overlay, pbindcfg},
444 	{ NULL, 0, NULL }
445 };
446 
447 static slap_verbmasks idassert_mode[] = {
448 	{ BER_BVC("self"),		LDAP_BACK_IDASSERT_SELF },
449 	{ BER_BVC("anonymous"),		LDAP_BACK_IDASSERT_ANONYMOUS },
450 	{ BER_BVC("none"),		LDAP_BACK_IDASSERT_NOASSERT },
451 	{ BER_BVC("legacy"),		LDAP_BACK_IDASSERT_LEGACY },
452 	{ BER_BVNULL,			0 }
453 };
454 
455 static slap_verbmasks tls_mode[] = {
456 	{ BER_BVC( "propagate" ),	LDAP_BACK_F_TLS_PROPAGATE_MASK },
457 	{ BER_BVC( "try-propagate" ),	LDAP_BACK_F_PROPAGATE_TLS },
458 	{ BER_BVC( "start" ),		LDAP_BACK_F_TLS_USE_MASK },
459 	{ BER_BVC( "try-start" ),	LDAP_BACK_F_USE_TLS },
460 	{ BER_BVC( "ldaps" ),		LDAP_BACK_F_TLS_LDAPS },
461 	{ BER_BVC( "none" ),		LDAP_BACK_F_NONE },
462 	{ BER_BVNULL,			0 }
463 };
464 
465 static slap_verbmasks t_f_mode[] = {
466 	{ BER_BVC( "yes" ),		LDAP_BACK_F_T_F },
467 	{ BER_BVC( "discover" ),	LDAP_BACK_F_T_F_DISCOVER },
468 	{ BER_BVC( "no" ),		LDAP_BACK_F_NONE },
469 	{ BER_BVNULL,			0 }
470 };
471 
472 static slap_verbmasks cancel_mode[] = {
473 	{ BER_BVC( "ignore" ),		LDAP_BACK_F_CANCEL_IGNORE },
474 	{ BER_BVC( "exop" ),		LDAP_BACK_F_CANCEL_EXOP },
475 	{ BER_BVC( "exop-discover" ),	LDAP_BACK_F_CANCEL_EXOP_DISCOVER },
476 	{ BER_BVC( "abandon" ),		LDAP_BACK_F_CANCEL_ABANDON },
477 	{ BER_BVNULL,			0 }
478 };
479 
480 /* see enum in slap.h */
481 static slap_cf_aux_table timeout_table[] = {
482 	{ BER_BVC("bind="),	SLAP_OP_BIND * sizeof( time_t ),	'u', 0, NULL },
483 	/* unbind makes no sense */
484 	{ BER_BVC("add="),	SLAP_OP_ADD * sizeof( time_t ),		'u', 0, NULL },
485 	{ BER_BVC("delete="),	SLAP_OP_DELETE * sizeof( time_t ),	'u', 0, NULL },
486 	{ BER_BVC("modrdn="),	SLAP_OP_MODRDN * sizeof( time_t ),	'u', 0, NULL },
487 	{ BER_BVC("modify="),	SLAP_OP_MODIFY * sizeof( time_t ),	'u', 0, NULL },
488 	{ BER_BVC("compare="),	SLAP_OP_COMPARE * sizeof( time_t ),	'u', 0, NULL },
489 	{ BER_BVC("search="),	SLAP_OP_SEARCH * sizeof( time_t ),	'u', 0, NULL },
490 	/* abandon makes little sense */
491 #if 0	/* not implemented yet */
492 	{ BER_BVC("extended="),	SLAP_OP_EXTENDED * sizeof( time_t ),	'u', 0, NULL },
493 #endif
494 	{ BER_BVNULL, 0, 0, 0, NULL }
495 };
496 
497 int
498 slap_retry_info_parse(
499 	char			*in,
500 	slap_retry_info_t 	*ri,
501 	char			*buf,
502 	ber_len_t		buflen )
503 {
504 	char			**retrylist = NULL;
505 	int			rc = 0;
506 	int			i;
507 
508 	slap_str2clist( &retrylist, in, " ;" );
509 	if ( retrylist == NULL ) {
510 		return 1;
511 	}
512 
513 	for ( i = 0; retrylist[ i ] != NULL; i++ )
514 		/* count */ ;
515 
516 	ri->ri_interval = ch_calloc( sizeof( time_t ), i + 1 );
517 	ri->ri_num = ch_calloc( sizeof( int ), i + 1 );
518 
519 	for ( i = 0; retrylist[ i ] != NULL; i++ ) {
520 		unsigned long	t;
521 		char		*sep = strchr( retrylist[ i ], ',' );
522 
523 		if ( sep == NULL ) {
524 			snprintf( buf, buflen,
525 				"missing comma in retry pattern #%d \"%s\"",
526 				i, retrylist[ i ] );
527 			rc = 1;
528 			goto done;
529 		}
530 
531 		*sep++ = '\0';
532 
533 		if ( lutil_parse_time( retrylist[ i ], &t ) ) {
534 			snprintf( buf, buflen,
535 				"unable to parse interval #%d \"%s\"",
536 				i, retrylist[ i ] );
537 			rc = 1;
538 			goto done;
539 		}
540 		ri->ri_interval[ i ] = (time_t)t;
541 
542 		if ( strcmp( sep, "+" ) == 0 ) {
543 			if ( retrylist[ i + 1 ] != NULL ) {
544 				snprintf( buf, buflen,
545 					"extra cruft after retry pattern "
546 					"#%d \"%s,+\" with \"forever\" mark",
547 					i, retrylist[ i ] );
548 				rc = 1;
549 				goto done;
550 			}
551 			ri->ri_num[ i ] = SLAP_RETRYNUM_FOREVER;
552 
553 		} else if ( lutil_atoi( &ri->ri_num[ i ], sep ) ) {
554 			snprintf( buf, buflen,
555 				"unable to parse retry num #%d \"%s\"",
556 				i, sep );
557 			rc = 1;
558 			goto done;
559 		}
560 	}
561 
562 	ri->ri_num[ i ] = SLAP_RETRYNUM_TAIL;
563 
564 	ri->ri_idx = 0;
565 	ri->ri_count = 0;
566 	ri->ri_last = (time_t)(-1);
567 
568 done:;
569 	ldap_charray_free( retrylist );
570 
571 	if ( rc ) {
572 		slap_retry_info_destroy( ri );
573 	}
574 
575 	return rc;
576 }
577 
578 int
579 slap_retry_info_unparse(
580 	slap_retry_info_t	*ri,
581 	struct berval		*bvout )
582 {
583 	char		buf[ BUFSIZ * 2 ],
584 			*ptr = buf;
585 	int		i, len, restlen = (int) sizeof( buf );
586 	struct berval	bv;
587 
588 	assert( ri != NULL );
589 	assert( bvout != NULL );
590 
591 	BER_BVZERO( bvout );
592 
593 	for ( i = 0; ri->ri_num[ i ] != SLAP_RETRYNUM_TAIL; i++ ) {
594 		if ( i > 0 ) {
595 			if ( --restlen <= 0 ) {
596 				return 1;
597 			}
598 			*ptr++ = ';';
599 		}
600 
601 		if ( lutil_unparse_time( ptr, restlen, ri->ri_interval[i] ) < 0 ) {
602 			return 1;
603 		}
604 		len = (int) strlen( ptr );
605 		if ( (restlen -= len + 1) <= 0 ) {
606 			return 1;
607 		}
608 		ptr += len;
609 		*ptr++ = ',';
610 
611 		if ( ri->ri_num[i] == SLAP_RETRYNUM_FOREVER ) {
612 			if ( --restlen <= 0 ) {
613 				return 1;
614 			}
615 			*ptr++ = '+';
616 
617 		} else {
618 			len = snprintf( ptr, restlen, "%d", ri->ri_num[i] );
619 			if ( (restlen -= len) <= 0 || len < 0 ) {
620 				return 1;
621 			}
622 			ptr += len;
623 		}
624 	}
625 
626 	bv.bv_val = buf;
627 	bv.bv_len = ptr - buf;
628 	ber_dupbv( bvout, &bv );
629 
630 	return 0;
631 }
632 
633 void
634 slap_retry_info_destroy(
635 	slap_retry_info_t	*ri )
636 {
637 	assert( ri != NULL );
638 
639 	assert( ri->ri_interval != NULL );
640 	ch_free( ri->ri_interval );
641 	ri->ri_interval = NULL;
642 
643 	assert( ri->ri_num != NULL );
644 	ch_free( ri->ri_num );
645 	ri->ri_num = NULL;
646 }
647 
648 static int
649 slap_idassert_authzfrom_parse( ConfigArgs *c, slap_idassert_t *si )
650 {
651 	struct berval	bv;
652 	struct berval	in;
653 	int		rc;
654 
655  	if ( strcmp( c->argv[ 1 ], "*" ) == 0
656  		|| strcmp( c->argv[ 1 ], "dn:*" ) == 0
657  		|| strcasecmp( c->argv[ 1 ], "dn.regex:.*" ) == 0 )
658  	{
659  		if ( si->si_authz != NULL ) {
660  			snprintf( c->cr_msg, sizeof( c->cr_msg ),
661  				"\"idassert-authzFrom <authz>\": "
662  				"\"%s\" conflicts with existing authz rules",
663  				c->argv[ 1 ] );
664  			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
665  			return 1;
666  		}
667 
668  		si->si_flags |= LDAP_BACK_AUTH_AUTHZ_ALL;
669 
670  		return 0;
671 
672  	} else if ( ( si->si_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) ) {
673   		snprintf( c->cr_msg, sizeof( c->cr_msg ),
674   			"\"idassert-authzFrom <authz>\": "
675  			"\"<authz>\" conflicts with \"*\"" );
676   		Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
677   		return 1;
678   	}
679 
680  	ber_str2bv( c->argv[ 1 ], 0, 0, &in );
681  	rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL );
682  	if ( rc != LDAP_SUCCESS ) {
683  		snprintf( c->cr_msg, sizeof( c->cr_msg ),
684  			"\"idassert-authzFrom <authz>\": "
685  			"invalid syntax" );
686  		Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
687  		return 1;
688  	}
689 
690 	if ( c->valx == -1 ) {
691 		ber_bvarray_add( &si->si_authz, &bv );
692 
693 	} else {
694 		int i = 0;
695 		if ( si->si_authz != NULL ) {
696 			for ( ; !BER_BVISNULL( &si->si_authz[ i ] ); i++ )
697 				;
698 		}
699 
700 		if ( i <= c->valx ) {
701 			ber_bvarray_add( &si->si_authz, &bv );
702 
703 		} else {
704 			BerVarray tmp = ber_memrealloc( si->si_authz,
705 				sizeof( struct berval )*( i + 2 ) );
706 			if ( tmp == NULL ) {
707 				return -1;
708 			}
709 			si->si_authz = tmp;
710 			for ( ; i > c->valx; i-- ) {
711 				si->si_authz[ i ] = si->si_authz[ i - 1 ];
712 			}
713 			si->si_authz[ c->valx ] = bv;
714 		}
715 	}
716 
717 	return 0;
718 }
719 
720 static int
721 slap_idassert_passthru_parse( ConfigArgs *c, slap_idassert_t *si )
722 {
723 	struct berval	bv;
724 	struct berval	in;
725 	int		rc;
726 
727  	ber_str2bv( c->argv[ 1 ], 0, 0, &in );
728  	rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL );
729  	if ( rc != LDAP_SUCCESS ) {
730  		snprintf( c->cr_msg, sizeof( c->cr_msg ),
731  			"\"idassert-passThru <authz>\": "
732  			"invalid syntax" );
733  		Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
734  		return 1;
735  	}
736 
737 	if ( c->valx == -1 ) {
738 		ber_bvarray_add( &si->si_passthru, &bv );
739 
740 	} else {
741 		int i = 0;
742 		if ( si->si_passthru != NULL ) {
743 			for ( ; !BER_BVISNULL( &si->si_passthru[ i ] ); i++ )
744 				;
745 		}
746 
747 		if ( i <= c->valx ) {
748 			ber_bvarray_add( &si->si_passthru, &bv );
749 
750 		} else {
751 			BerVarray tmp = ber_memrealloc( si->si_passthru,
752 				sizeof( struct berval )*( i + 2 ) );
753 			if ( tmp == NULL ) {
754 				return -1;
755 			}
756 			si->si_passthru = tmp;
757 			for ( ; i > c->valx; i-- ) {
758 				si->si_passthru[ i ] = si->si_passthru[ i - 1 ];
759 			}
760 			si->si_passthru[ c->valx ] = bv;
761 		}
762 	}
763 
764 	return 0;
765 }
766 
767 static int
768 slap_idassert_parse( ConfigArgs *c, slap_idassert_t *si )
769 {
770 	int		i;
771 
772 	for ( i = 1; i < c->argc; i++ ) {
773 		if ( strncasecmp( c->argv[ i ], "mode=", STRLENOF( "mode=" ) ) == 0 ) {
774 			char	*argvi = c->argv[ i ] + STRLENOF( "mode=" );
775 			int	j;
776 
777 			j = verb_to_mask( argvi, idassert_mode );
778 			if ( BER_BVISNULL( &idassert_mode[ j ].word ) ) {
779 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
780 					"\"idassert-bind <args>\": "
781 					"unknown mode \"%s\"",
782 					argvi );
783 				Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
784 				return 1;
785 			}
786 
787 			si->si_mode = idassert_mode[ j ].mask;
788 
789 		} else if ( strncasecmp( c->argv[ i ], "authz=", STRLENOF( "authz=" ) ) == 0 ) {
790 			char	*argvi = c->argv[ i ] + STRLENOF( "authz=" );
791 
792 			if ( strcasecmp( argvi, "native" ) == 0 ) {
793 				if ( si->si_bc.sb_method != LDAP_AUTH_SASL ) {
794 					snprintf( c->cr_msg, sizeof( c->cr_msg ),
795 						"\"idassert-bind <args>\": "
796 						"authz=\"native\" incompatible "
797 						"with auth method" );
798 					Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
799 					return 1;
800 				}
801 				si->si_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
802 
803 			} else if ( strcasecmp( argvi, "proxyAuthz" ) == 0 ) {
804 				si->si_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
805 
806 			} else {
807 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
808 					"\"idassert-bind <args>\": "
809 					"unknown authz \"%s\"",
810 					argvi );
811 				Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
812 				return 1;
813 			}
814 
815 		} else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 ) {
816 			char	*argvi = c->argv[ i ] + STRLENOF( "flags=" );
817 			char	**flags = ldap_str2charray( argvi, "," );
818 			int	j, err = 0;
819 
820 			if ( flags == NULL ) {
821 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
822 					"\"idassert-bind <args>\": "
823 					"unable to parse flags \"%s\"",
824 					argvi );
825 				Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
826 				return 1;
827 			}
828 
829 			for ( j = 0; flags[ j ] != NULL; j++ ) {
830 
831 				if ( strcasecmp( flags[ j ], "override" ) == 0 ) {
832 					si->si_flags |= LDAP_BACK_AUTH_OVERRIDE;
833 
834 				} else if ( strcasecmp( flags[ j ], "prescriptive" ) == 0 ) {
835 					si->si_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
836 
837 				} else if ( strcasecmp( flags[ j ], "non-prescriptive" ) == 0 ) {
838 					si->si_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
839 
840 				} else if ( strcasecmp( flags[ j ], "obsolete-proxy-authz" ) == 0 ) {
841 					if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
842 						Debug( LDAP_DEBUG_ANY,
843                                       		 		"%s: \"obsolete-proxy-authz\" flag "
844                                       		 		"in \"idassert-mode <args>\" "
845                                       		 		"incompatible with previously issued \"obsolete-encoding-workaround\" flag.\n",
846                                       	 			c->log, 0, 0 );
847 						err = 1;
848 						break;
849 
850 					} else {
851 						si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ;
852 					}
853 
854 				} else if ( strcasecmp( flags[ j ], "obsolete-encoding-workaround" ) == 0 ) {
855 					if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
856 						Debug( LDAP_DEBUG_ANY,
857                                       	 			"%s: \"obsolete-encoding-workaround\" flag "
858                                        			"in \"idassert-mode <args>\" "
859                                        			"incompatible with previously issued \"obsolete-proxy-authz\" flag.\n",
860                                        			c->log, 0, 0 );
861 						err = 1;
862 						break;
863 
864 					} else {
865 						si->si_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND;
866 					}
867 
868 				} else if ( strcasecmp( flags[ j ], "proxy-authz-critical" ) == 0 ) {
869 					si->si_flags |= LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL;
870 
871 				} else if ( strcasecmp( flags[ j ], "proxy-authz-non-critical" ) == 0 ) {
872 					si->si_flags &= ~LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL;
873 
874 				} else {
875 					snprintf( c->cr_msg, sizeof( c->cr_msg ),
876 						"\"idassert-bind <args>\": "
877 						"unknown flag \"%s\"",
878 						flags[ j ] );
879 					Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
880 					err = 1;
881 					break;
882 				}
883 			}
884 
885 			ldap_charray_free( flags );
886 			if ( err ) {
887 				return 1;
888 			}
889 
890 		} else if ( bindconf_parse( c->argv[ i ], &si->si_bc ) ) {
891 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
892 				"\"idassert-bind <args>\": "
893 				"unable to parse field \"%s\"",
894 				c->argv[ i ] );
895 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
896 			return 1;
897 		}
898 	}
899 
900 	if ( si->si_bc.sb_method == LDAP_AUTH_SIMPLE ) {
901 		if ( BER_BVISNULL( &si->si_bc.sb_binddn )
902 			|| BER_BVISNULL( &si->si_bc.sb_cred ) )
903 		{
904 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
905 				"\"idassert-bind <args>\": "
906 				"SIMPLE needs \"binddn\" and \"credentials\"" );
907 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
908 			return 1;
909 		}
910 	}
911 
912 	bindconf_tls_defaults( &si->si_bc );
913 
914 	return 0;
915 }
916 
917 /* NOTE: temporary, until back-meta is ported to back-config */
918 int
919 slap_idassert_authzfrom_parse_cf( const char *fname, int lineno, const char *arg, slap_idassert_t *si )
920 {
921 	ConfigArgs	c = { 0 };
922 	char		*argv[ 3 ];
923 
924 	snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
925 	c.argc = 2;
926 	c.argv = argv;
927 	argv[ 0 ] = "idassert-authzFrom";
928 	argv[ 1 ] = (char *)arg;
929 	argv[ 2 ] = NULL;
930 
931 	return slap_idassert_authzfrom_parse( &c, si );
932 }
933 
934 int
935 slap_idassert_passthru_parse_cf( const char *fname, int lineno, const char *arg, slap_idassert_t *si )
936 {
937 	ConfigArgs	c = { 0 };
938 	char		*argv[ 3 ];
939 
940 	snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
941 	c.argc = 2;
942 	c.argv = argv;
943 	argv[ 0 ] = "idassert-passThru";
944 	argv[ 1 ] = (char *)arg;
945 	argv[ 2 ] = NULL;
946 
947 	return slap_idassert_passthru_parse( &c, si );
948 }
949 
950 int
951 slap_idassert_parse_cf( const char *fname, int lineno, int argc, char *argv[], slap_idassert_t *si )
952 {
953 	ConfigArgs	c = { 0 };
954 
955 	snprintf( c.log, sizeof( c.log ), "%s: line %d", fname, lineno );
956 	c.argc = argc;
957 	c.argv = argv;
958 
959 	return slap_idassert_parse( &c, si );
960 }
961 
962 static int
963 ldap_back_cf_gen( ConfigArgs *c )
964 {
965 	ldapinfo_t	*li = ( ldapinfo_t * )c->be->be_private;
966 	int		rc = 0;
967 	int		i;
968 
969 	if ( c->op == SLAP_CONFIG_EMIT ) {
970 		struct berval	bv = BER_BVNULL;
971 
972 		if ( li == NULL ) {
973 			return 1;
974 		}
975 
976 		switch( c->type ) {
977 		case LDAP_BACK_CFG_URI:
978 			if ( li->li_uri != NULL ) {
979 				struct berval	bv, bv2;
980 
981 				ber_str2bv( li->li_uri, 0, 0, &bv );
982 				bv2.bv_len = bv.bv_len + STRLENOF( "\"\"" );
983 				bv2.bv_val = ch_malloc( bv2.bv_len + 1 );
984 				snprintf( bv2.bv_val, bv2.bv_len + 1,
985 					"\"%s\"", bv.bv_val );
986 				ber_bvarray_add( &c->rvalue_vals, &bv2 );
987 
988 			} else {
989 				rc = 1;
990 			}
991 			break;
992 
993 		case LDAP_BACK_CFG_TLS: {
994 			struct berval bc = BER_BVNULL, bv2;
995 			enum_to_verb( tls_mode, ( li->li_flags & LDAP_BACK_F_TLS_MASK ), &bv );
996 			assert( !BER_BVISNULL( &bv ) );
997 			bindconf_tls_unparse( &li->li_tls, &bc );
998 
999 			if ( !BER_BVISEMPTY( &bc )) {
1000 				bv2.bv_len = bv.bv_len + bc.bv_len + 1;
1001 				bv2.bv_val = ch_malloc( bv2.bv_len + 1 );
1002 				strcpy( bv2.bv_val, bv.bv_val );
1003 				bv2.bv_val[bv.bv_len] = ' ';
1004 				strcpy( &bv2.bv_val[bv.bv_len + 1], bc.bv_val );
1005 				ber_bvarray_add( &c->rvalue_vals, &bv2 );
1006 
1007 			} else {
1008 				value_add_one( &c->rvalue_vals, &bv );
1009 			}
1010 			ber_memfree( bc.bv_val );
1011 			}
1012 			break;
1013 
1014 		case LDAP_BACK_CFG_ACL_AUTHCDN:
1015 		case LDAP_BACK_CFG_ACL_PASSWD:
1016 		case LDAP_BACK_CFG_ACL_METHOD:
1017 			/* handled by LDAP_BACK_CFG_ACL_BIND */
1018 			rc = 1;
1019 			break;
1020 
1021 		case LDAP_BACK_CFG_ACL_BIND: {
1022 			int	i;
1023 
1024 			if ( li->li_acl_authmethod == LDAP_AUTH_NONE ) {
1025 				return 1;
1026 			}
1027 
1028 			bindconf_unparse( &li->li_acl, &bv );
1029 
1030 			for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ )
1031 				/* count spaces */ ;
1032 
1033 			if ( i ) {
1034 				bv.bv_len -= i;
1035 				AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ],
1036 					bv.bv_len + 1 );
1037 			}
1038 
1039 			ber_bvarray_add( &c->rvalue_vals, &bv );
1040 			break;
1041 		}
1042 
1043 		case LDAP_BACK_CFG_IDASSERT_MODE:
1044 		case LDAP_BACK_CFG_IDASSERT_AUTHCDN:
1045 		case LDAP_BACK_CFG_IDASSERT_PASSWD:
1046 		case LDAP_BACK_CFG_IDASSERT_METHOD:
1047 			/* handled by LDAP_BACK_CFG_IDASSERT_BIND */
1048 			rc = 1;
1049 			break;
1050 
1051 		case LDAP_BACK_CFG_IDASSERT_AUTHZFROM:
1052 		case LDAP_BACK_CFG_IDASSERT_PASSTHRU: {
1053 			BerVarray	*bvp;
1054 			int		i;
1055 			struct berval	bv = BER_BVNULL;
1056 			char		buf[SLAP_TEXT_BUFLEN];
1057 
1058 			switch ( c->type ) {
1059 			case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: bvp = &li->li_idassert_authz; break;
1060 			case LDAP_BACK_CFG_IDASSERT_PASSTHRU: bvp = &li->li_idassert_passthru; break;
1061 			default: assert( 0 ); break;
1062 			}
1063 
1064 			if ( *bvp == NULL ) {
1065 				if ( bvp == &li->li_idassert_authz
1066 					&& ( li->li_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) )
1067 				{
1068 					BER_BVSTR( &bv, "*" );
1069 					value_add_one( &c->rvalue_vals, &bv );
1070 
1071 				} else {
1072 					rc = 1;
1073 				}
1074 				break;
1075 			}
1076 
1077 			for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ ) {
1078 				char *ptr;
1079 				int len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i );
1080 				bv.bv_len = ((*bvp)[ i ]).bv_len + len;
1081 				bv.bv_val = ber_memrealloc( bv.bv_val, bv.bv_len + 1 );
1082 				ptr = bv.bv_val;
1083 				ptr = lutil_strcopy( ptr, buf );
1084 				ptr = lutil_strncopy( ptr, ((*bvp)[ i ]).bv_val, ((*bvp)[ i ]).bv_len );
1085 				value_add_one( &c->rvalue_vals, &bv );
1086 			}
1087 			if ( bv.bv_val ) {
1088 				ber_memfree( bv.bv_val );
1089 			}
1090 			break;
1091 		}
1092 
1093 		case LDAP_BACK_CFG_IDASSERT_BIND: {
1094 			int		i;
1095 			struct berval	bc = BER_BVNULL;
1096 			char		*ptr;
1097 
1098 			if ( li->li_idassert_authmethod == LDAP_AUTH_NONE ) {
1099 				return 1;
1100 			}
1101 
1102 			if ( li->li_idassert_authmethod != LDAP_AUTH_NONE ) {
1103 				ber_len_t	len;
1104 
1105 				switch ( li->li_idassert_mode ) {
1106 				case LDAP_BACK_IDASSERT_OTHERID:
1107 				case LDAP_BACK_IDASSERT_OTHERDN:
1108 					break;
1109 
1110 				default: {
1111 					struct berval	mode = BER_BVNULL;
1112 
1113 					enum_to_verb( idassert_mode, li->li_idassert_mode, &mode );
1114 					if ( BER_BVISNULL( &mode ) ) {
1115 						/* there's something wrong... */
1116 						assert( 0 );
1117 						rc = 1;
1118 
1119 					} else {
1120 						bv.bv_len = STRLENOF( "mode=" ) + mode.bv_len;
1121 						bv.bv_val = ch_malloc( bv.bv_len + 1 );
1122 
1123 						ptr = lutil_strcopy( bv.bv_val, "mode=" );
1124 						ptr = lutil_strcopy( ptr, mode.bv_val );
1125 					}
1126 					break;
1127 				}
1128 				}
1129 
1130 				if ( li->li_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) {
1131 					len = bv.bv_len + STRLENOF( "authz=native" );
1132 
1133 					if ( !BER_BVISEMPTY( &bv ) ) {
1134 						len += STRLENOF( " " );
1135 					}
1136 
1137 					bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
1138 
1139 					ptr = &bv.bv_val[ bv.bv_len ];
1140 
1141 					if ( !BER_BVISEMPTY( &bv ) ) {
1142 						ptr = lutil_strcopy( ptr, " " );
1143 					}
1144 
1145 					(void)lutil_strcopy( ptr, "authz=native" );
1146 				}
1147 
1148 				len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override,obsolete-encoding-workaround,proxy-authz-non-critical" );
1149 				/* flags */
1150 				if ( !BER_BVISEMPTY( &bv ) ) {
1151 					len += STRLENOF( " " );
1152 				}
1153 
1154 				bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
1155 
1156 				ptr = &bv.bv_val[ bv.bv_len ];
1157 
1158 				if ( !BER_BVISEMPTY( &bv ) ) {
1159 					ptr = lutil_strcopy( ptr, " " );
1160 				}
1161 
1162 				ptr = lutil_strcopy( ptr, "flags=" );
1163 
1164 				if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
1165 					ptr = lutil_strcopy( ptr, "prescriptive" );
1166 				} else {
1167 					ptr = lutil_strcopy( ptr, "non-prescriptive" );
1168 				}
1169 
1170 				if ( li->li_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
1171 					ptr = lutil_strcopy( ptr, ",override" );
1172 				}
1173 
1174 				if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
1175 					ptr = lutil_strcopy( ptr, ",obsolete-proxy-authz" );
1176 
1177 				} else if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
1178 					ptr = lutil_strcopy( ptr, ",obsolete-encoding-workaround" );
1179 				}
1180 
1181 				if ( li->li_idassert_flags & LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL ) {
1182 					ptr = lutil_strcopy( ptr, ",proxy-authz-critical" );
1183 
1184 				} else {
1185 					ptr = lutil_strcopy( ptr, ",proxy-authz-non-critical" );
1186 				}
1187 
1188 				bv.bv_len = ( ptr - bv.bv_val );
1189 				/* end-of-flags */
1190 			}
1191 
1192 			bindconf_unparse( &li->li_idassert.si_bc, &bc );
1193 
1194 			if ( !BER_BVISNULL( &bv ) ) {
1195 				ber_len_t	len = bv.bv_len + bc.bv_len;
1196 
1197 				bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
1198 
1199 				assert( bc.bv_val[ 0 ] == ' ' );
1200 
1201 				ptr = lutil_strcopy( &bv.bv_val[ bv.bv_len ], bc.bv_val );
1202 				free( bc.bv_val );
1203 				bv.bv_len = ptr - bv.bv_val;
1204 
1205 			} else {
1206 				for ( i = 0; isspace( (unsigned char) bc.bv_val[ i ] ); i++ )
1207 					/* count spaces */ ;
1208 
1209 				if ( i ) {
1210 					bc.bv_len -= i;
1211 					AC_MEMCPY( bc.bv_val, &bc.bv_val[ i ], bc.bv_len + 1 );
1212 				}
1213 
1214 				bv = bc;
1215 			}
1216 
1217 			ber_bvarray_add( &c->rvalue_vals, &bv );
1218 
1219 			break;
1220 		}
1221 
1222 		case LDAP_BACK_CFG_REBIND:
1223 			c->value_int = LDAP_BACK_SAVECRED( li );
1224 			break;
1225 
1226 		case LDAP_BACK_CFG_CHASE:
1227 			c->value_int = LDAP_BACK_CHASE_REFERRALS( li );
1228 			break;
1229 
1230 		case LDAP_BACK_CFG_T_F:
1231 			enum_to_verb( t_f_mode, (li->li_flags & LDAP_BACK_F_T_F_MASK2), &bv );
1232 			if ( BER_BVISNULL( &bv ) ) {
1233 				/* there's something wrong... */
1234 				assert( 0 );
1235 				rc = 1;
1236 
1237 			} else {
1238 				value_add_one( &c->rvalue_vals, &bv );
1239 			}
1240 			break;
1241 
1242 		case LDAP_BACK_CFG_WHOAMI:
1243 			c->value_int = LDAP_BACK_PROXY_WHOAMI( li );
1244 			break;
1245 
1246 		case LDAP_BACK_CFG_TIMEOUT:
1247 			BER_BVZERO( &bv );
1248 
1249 			for ( i = 0; i < SLAP_OP_LAST; i++ ) {
1250 				if ( li->li_timeout[ i ] != 0 ) {
1251 					break;
1252 				}
1253 			}
1254 
1255 			if ( i == SLAP_OP_LAST ) {
1256 				return 1;
1257 			}
1258 
1259 			slap_cf_aux_table_unparse( li->li_timeout, &bv, timeout_table );
1260 
1261 			if ( BER_BVISNULL( &bv ) ) {
1262 				return 1;
1263 			}
1264 
1265 			for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ )
1266 				/* count spaces */ ;
1267 
1268 			if ( i ) {
1269 				bv.bv_len -= i;
1270 				AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ],
1271 					bv.bv_len + 1 );
1272 			}
1273 
1274 			ber_bvarray_add( &c->rvalue_vals, &bv );
1275 			break;
1276 
1277 		case LDAP_BACK_CFG_IDLE_TIMEOUT: {
1278 			char	buf[ SLAP_TEXT_BUFLEN ];
1279 
1280 			if ( li->li_idle_timeout == 0 ) {
1281 				return 1;
1282 			}
1283 
1284 			lutil_unparse_time( buf, sizeof( buf ), li->li_idle_timeout );
1285 			ber_str2bv( buf, 0, 0, &bv );
1286 			value_add_one( &c->rvalue_vals, &bv );
1287 			} break;
1288 
1289 		case LDAP_BACK_CFG_CONN_TTL: {
1290 			char	buf[ SLAP_TEXT_BUFLEN ];
1291 
1292 			if ( li->li_conn_ttl == 0 ) {
1293 				return 1;
1294 			}
1295 
1296 			lutil_unparse_time( buf, sizeof( buf ), li->li_conn_ttl );
1297 			ber_str2bv( buf, 0, 0, &bv );
1298 			value_add_one( &c->rvalue_vals, &bv );
1299 			} break;
1300 
1301 		case LDAP_BACK_CFG_NETWORK_TIMEOUT: {
1302 			char	buf[ SLAP_TEXT_BUFLEN ];
1303 
1304 			if ( li->li_network_timeout == 0 ) {
1305 				return 1;
1306 			}
1307 
1308 			snprintf( buf, sizeof( buf ), "%ld",
1309 				(long)li->li_network_timeout );
1310 			ber_str2bv( buf, 0, 0, &bv );
1311 			value_add_one( &c->rvalue_vals, &bv );
1312 			} break;
1313 
1314 		case LDAP_BACK_CFG_VERSION:
1315 			if ( li->li_version == 0 ) {
1316 				return 1;
1317 			}
1318 
1319 			c->value_int = li->li_version;
1320 			break;
1321 
1322 		case LDAP_BACK_CFG_SINGLECONN:
1323 			c->value_int = LDAP_BACK_SINGLECONN( li );
1324 			break;
1325 
1326 		case LDAP_BACK_CFG_USETEMP:
1327 			c->value_int = LDAP_BACK_USE_TEMPORARIES( li );
1328 			break;
1329 
1330 		case LDAP_BACK_CFG_CONNPOOLMAX:
1331 			c->value_int = li->li_conn_priv_max;
1332 			break;
1333 
1334 		case LDAP_BACK_CFG_CANCEL: {
1335 			slap_mask_t	mask = LDAP_BACK_F_CANCEL_MASK2;
1336 
1337 			if ( LDAP_BACK_CANCEL_DISCOVER( li ) ) {
1338 				mask &= ~LDAP_BACK_F_CANCEL_EXOP;
1339 			}
1340 			enum_to_verb( cancel_mode, (li->li_flags & mask), &bv );
1341 			if ( BER_BVISNULL( &bv ) ) {
1342 				/* there's something wrong... */
1343 				assert( 0 );
1344 				rc = 1;
1345 
1346 			} else {
1347 				value_add_one( &c->rvalue_vals, &bv );
1348 			}
1349 			} break;
1350 
1351 		case LDAP_BACK_CFG_QUARANTINE:
1352 			if ( !LDAP_BACK_QUARANTINE( li ) ) {
1353 				rc = 1;
1354 				break;
1355 			}
1356 
1357 			rc = slap_retry_info_unparse( &li->li_quarantine, &bv );
1358 			if ( rc == 0 ) {
1359 				ber_bvarray_add( &c->rvalue_vals, &bv );
1360 			}
1361 			break;
1362 
1363 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
1364 		case LDAP_BACK_CFG_ST_REQUEST:
1365 			c->value_int = LDAP_BACK_ST_REQUEST( li );
1366 			break;
1367 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
1368 
1369 		case LDAP_BACK_CFG_NOREFS:
1370 			c->value_int = LDAP_BACK_NOREFS( li );
1371 			break;
1372 
1373 		case LDAP_BACK_CFG_NOUNDEFFILTER:
1374 			c->value_int = LDAP_BACK_NOUNDEFFILTER( li );
1375 			break;
1376 
1377 		default:
1378 			/* FIXME: we need to handle all... */
1379 			assert( 0 );
1380 			break;
1381 		}
1382 		return rc;
1383 
1384 	} else if ( c->op == LDAP_MOD_DELETE ) {
1385 		switch( c->type ) {
1386 		case LDAP_BACK_CFG_URI:
1387 			if ( li->li_uri != NULL ) {
1388 				ch_free( li->li_uri );
1389 				li->li_uri = NULL;
1390 
1391 				assert( li->li_bvuri != NULL );
1392 				ber_bvarray_free( li->li_bvuri );
1393 				li->li_bvuri = NULL;
1394 			}
1395 
1396 			/* better cleanup the cached connections... */
1397 			/* NOTE: don't worry about locking: if we got here,
1398 			 * other threads are suspended. */
1399 			if ( li->li_conninfo.lai_tree != NULL ) {
1400 				avl_free( li->li_conninfo.lai_tree, ldap_back_conn_free );
1401 				li->li_conninfo.lai_tree = NULL;
1402 			}
1403 
1404 			break;
1405 
1406 		case LDAP_BACK_CFG_TLS:
1407 			rc = 1;
1408 			break;
1409 
1410 		case LDAP_BACK_CFG_ACL_AUTHCDN:
1411 		case LDAP_BACK_CFG_ACL_PASSWD:
1412 		case LDAP_BACK_CFG_ACL_METHOD:
1413 			/* handled by LDAP_BACK_CFG_ACL_BIND */
1414 			rc = 1;
1415 			break;
1416 
1417 		case LDAP_BACK_CFG_ACL_BIND:
1418 			bindconf_free( &li->li_acl );
1419 			break;
1420 
1421 		case LDAP_BACK_CFG_IDASSERT_MODE:
1422 		case LDAP_BACK_CFG_IDASSERT_AUTHCDN:
1423 		case LDAP_BACK_CFG_IDASSERT_PASSWD:
1424 		case LDAP_BACK_CFG_IDASSERT_METHOD:
1425 			/* handled by LDAP_BACK_CFG_IDASSERT_BIND */
1426 			rc = 1;
1427 			break;
1428 
1429 		case LDAP_BACK_CFG_IDASSERT_AUTHZFROM:
1430 		case LDAP_BACK_CFG_IDASSERT_PASSTHRU: {
1431 			BerVarray *bvp;
1432 
1433 			switch ( c->type ) {
1434 			case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: bvp = &li->li_idassert_authz; break;
1435 			case LDAP_BACK_CFG_IDASSERT_PASSTHRU: bvp = &li->li_idassert_passthru; break;
1436 			default: assert( 0 ); break;
1437 			}
1438 
1439 			if ( c->valx < 0 ) {
1440 				if ( *bvp != NULL ) {
1441 					ber_bvarray_free( *bvp );
1442 					*bvp = NULL;
1443 				}
1444 
1445 			} else {
1446 				int i;
1447 
1448 				if ( *bvp == NULL ) {
1449 					rc = 1;
1450 					break;
1451 				}
1452 
1453 				for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ )
1454 					;
1455 
1456 				if ( i >= c->valx ) {
1457 					rc = 1;
1458 					break;
1459 				}
1460 				ber_memfree( ((*bvp)[ c->valx ]).bv_val );
1461 				for ( i = c->valx; !BER_BVISNULL( &((*bvp)[ i + 1 ]) ); i++ ) {
1462 					(*bvp)[ i ] = (*bvp)[ i + 1 ];
1463 				}
1464 				BER_BVZERO( &((*bvp)[ i ]) );
1465 			}
1466 			} break;
1467 
1468 		case LDAP_BACK_CFG_IDASSERT_BIND:
1469 			bindconf_free( &li->li_idassert.si_bc );
1470 			memset( &li->li_idassert, 0, sizeof( slap_idassert_t ) );
1471 			break;
1472 
1473 		case LDAP_BACK_CFG_REBIND:
1474 		case LDAP_BACK_CFG_CHASE:
1475 		case LDAP_BACK_CFG_T_F:
1476 		case LDAP_BACK_CFG_WHOAMI:
1477 		case LDAP_BACK_CFG_CANCEL:
1478 			rc = 1;
1479 			break;
1480 
1481 		case LDAP_BACK_CFG_TIMEOUT:
1482 			for ( i = 0; i < SLAP_OP_LAST; i++ ) {
1483 				li->li_timeout[ i ] = 0;
1484 			}
1485 			break;
1486 
1487 		case LDAP_BACK_CFG_IDLE_TIMEOUT:
1488 			li->li_idle_timeout = 0;
1489 			break;
1490 
1491 		case LDAP_BACK_CFG_CONN_TTL:
1492 			li->li_conn_ttl = 0;
1493 			break;
1494 
1495 		case LDAP_BACK_CFG_NETWORK_TIMEOUT:
1496 			li->li_network_timeout = 0;
1497 			break;
1498 
1499 		case LDAP_BACK_CFG_VERSION:
1500 			li->li_version = 0;
1501 			break;
1502 
1503 		case LDAP_BACK_CFG_SINGLECONN:
1504 			li->li_flags &= ~LDAP_BACK_F_SINGLECONN;
1505 			break;
1506 
1507 		case LDAP_BACK_CFG_USETEMP:
1508 			li->li_flags &= ~LDAP_BACK_F_USE_TEMPORARIES;
1509 			break;
1510 
1511 		case LDAP_BACK_CFG_CONNPOOLMAX:
1512 			li->li_conn_priv_max = LDAP_BACK_CONN_PRIV_MIN;
1513 			break;
1514 
1515 		case LDAP_BACK_CFG_QUARANTINE:
1516 			if ( !LDAP_BACK_QUARANTINE( li ) ) {
1517 				break;
1518 			}
1519 
1520 			slap_retry_info_destroy( &li->li_quarantine );
1521 			ldap_pvt_thread_mutex_destroy( &li->li_quarantine_mutex );
1522 			li->li_isquarantined = 0;
1523 			li->li_flags &= ~LDAP_BACK_F_QUARANTINE;
1524 			break;
1525 
1526 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
1527 		case LDAP_BACK_CFG_ST_REQUEST:
1528 			li->li_flags &= ~LDAP_BACK_F_ST_REQUEST;
1529 			break;
1530 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
1531 
1532 		case LDAP_BACK_CFG_NOREFS:
1533 			li->li_flags &= ~LDAP_BACK_F_NOREFS;
1534 			break;
1535 
1536 		case LDAP_BACK_CFG_NOUNDEFFILTER:
1537 			li->li_flags &= ~LDAP_BACK_F_NOUNDEFFILTER;
1538 			break;
1539 
1540 		default:
1541 			/* FIXME: we need to handle all... */
1542 			assert( 0 );
1543 			break;
1544 		}
1545 		return rc;
1546 
1547 	}
1548 
1549 	switch( c->type ) {
1550 	case LDAP_BACK_CFG_URI: {
1551 		LDAPURLDesc	*tmpludp, *lud;
1552 		char		**urllist = NULL;
1553 		int		urlrc = LDAP_URL_SUCCESS, i;
1554 
1555 		if ( li->li_uri != NULL ) {
1556 			ch_free( li->li_uri );
1557 			li->li_uri = NULL;
1558 
1559 			assert( li->li_bvuri != NULL );
1560 			ber_bvarray_free( li->li_bvuri );
1561 			li->li_bvuri = NULL;
1562 		}
1563 
1564 		/* PARANOID: DN and more are not required nor allowed */
1565 		urlrc = ldap_url_parselist_ext( &lud, c->argv[ 1 ], ", \t", LDAP_PVT_URL_PARSE_NONE );
1566 		if ( urlrc != LDAP_URL_SUCCESS ) {
1567 			char	*why;
1568 
1569 			switch ( urlrc ) {
1570 			case LDAP_URL_ERR_MEM:
1571 				why = "no memory";
1572 				break;
1573 			case LDAP_URL_ERR_PARAM:
1574 		  		why = "parameter is bad";
1575 				break;
1576 			case LDAP_URL_ERR_BADSCHEME:
1577 				why = "URL doesn't begin with \"[c]ldap[si]://\"";
1578 				break;
1579 			case LDAP_URL_ERR_BADENCLOSURE:
1580 				why = "URL is missing trailing \">\"";
1581 				break;
1582 			case LDAP_URL_ERR_BADURL:
1583 				why = "URL is bad";
1584 				break;
1585 			case LDAP_URL_ERR_BADHOST:
1586 				why = "host/port is bad";
1587 				break;
1588 			case LDAP_URL_ERR_BADATTRS:
1589 				why = "bad (or missing) attributes";
1590 				break;
1591 			case LDAP_URL_ERR_BADSCOPE:
1592 				why = "scope string is invalid (or missing)";
1593 				break;
1594 			case LDAP_URL_ERR_BADFILTER:
1595 				why = "bad or missing filter";
1596 				break;
1597 			case LDAP_URL_ERR_BADEXTS:
1598 				why = "bad or missing extensions";
1599 				break;
1600 			default:
1601 				why = "unknown reason";
1602 				break;
1603 			}
1604 			snprintf( c->cr_msg, sizeof( c->cr_msg),
1605 					"unable to parse uri \"%s\" "
1606 					"in \"uri <uri>\" line: %s",
1607 					c->value_string, why );
1608 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1609 			urlrc = 1;
1610 			goto done_url;
1611 		}
1612 
1613 		for ( i = 0, tmpludp = lud;
1614 				tmpludp;
1615 				i++, tmpludp = tmpludp->lud_next )
1616 		{
1617 			if ( ( tmpludp->lud_dn != NULL
1618 						&& tmpludp->lud_dn[0] != '\0' )
1619 					|| tmpludp->lud_attrs != NULL
1620 					/* || tmpludp->lud_scope != LDAP_SCOPE_DEFAULT */
1621 					|| tmpludp->lud_filter != NULL
1622 					|| tmpludp->lud_exts != NULL )
1623 			{
1624 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
1625 						"warning, only protocol, "
1626 						"host and port allowed "
1627 						"in \"uri <uri>\" statement "
1628 						"for uri #%d of \"%s\"",
1629 						i, c->argv[ 1 ] );
1630 				Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1631 			}
1632 		}
1633 
1634 		for ( i = 0, tmpludp = lud;
1635 				tmpludp;
1636 				i++, tmpludp = tmpludp->lud_next )
1637 			/* just count */
1638 			;
1639 		urllist = ch_calloc( sizeof( char * ), i + 1 );
1640 
1641 		for ( i = 0, tmpludp = lud;
1642 				tmpludp;
1643 				i++, tmpludp = tmpludp->lud_next )
1644 		{
1645 			LDAPURLDesc	tmplud;
1646 
1647 			tmplud = *tmpludp;
1648 			tmplud.lud_dn = "";
1649 			tmplud.lud_attrs = NULL;
1650 			tmplud.lud_filter = NULL;
1651 			if ( !ldap_is_ldapi_url( tmplud.lud_scheme ) ) {
1652 				tmplud.lud_exts = NULL;
1653 				tmplud.lud_crit_exts = 0;
1654 			}
1655 
1656 			urllist[ i ]  = ldap_url_desc2str( &tmplud );
1657 
1658 			if ( urllist[ i ] == NULL ) {
1659 				snprintf( c->cr_msg, sizeof( c->cr_msg),
1660 					"unable to rebuild uri "
1661 					"in \"uri <uri>\" statement "
1662 					"for \"%s\"",
1663 					c->argv[ 1 ] );
1664 				Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1665 				urlrc = 1;
1666 				goto done_url;
1667 			}
1668 		}
1669 
1670 		li->li_uri = ldap_charray2str( urllist, " " );
1671 		for ( i = 0; urllist[ i ] != NULL; i++ ) {
1672 			struct berval	bv;
1673 
1674 			ber_str2bv( urllist[ i ], 0, 0, &bv );
1675 			ber_bvarray_add( &li->li_bvuri, &bv );
1676 			urllist[ i ] = NULL;
1677 		}
1678 		ldap_memfree( urllist );
1679 		urllist = NULL;
1680 
1681 done_url:;
1682 		if ( urllist ) {
1683 			ldap_charray_free( urllist );
1684 		}
1685 		if ( lud ) {
1686 			ldap_free_urllist( lud );
1687 		}
1688 		if ( urlrc != LDAP_URL_SUCCESS ) {
1689 			return 1;
1690 		}
1691 		break;
1692 	}
1693 
1694 	case LDAP_BACK_CFG_TLS:
1695 		i = verb_to_mask( c->argv[1], tls_mode );
1696 		if ( BER_BVISNULL( &tls_mode[i].word ) ) {
1697 			return 1;
1698 		}
1699 		li->li_flags &= ~LDAP_BACK_F_TLS_MASK;
1700 		li->li_flags |= tls_mode[i].mask;
1701 		if ( c->argc > 2 ) {
1702 			for ( i=2; i<c->argc; i++ ) {
1703 				if ( bindconf_tls_parse( c->argv[i], &li->li_tls ))
1704 					return 1;
1705 			}
1706 			bindconf_tls_defaults( &li->li_tls );
1707 		}
1708 		break;
1709 
1710 	case LDAP_BACK_CFG_ACL_AUTHCDN:
1711 		switch ( li->li_acl_authmethod ) {
1712 		case LDAP_AUTH_NONE:
1713 			li->li_acl_authmethod = LDAP_AUTH_SIMPLE;
1714 			break;
1715 
1716 		case LDAP_AUTH_SIMPLE:
1717 			break;
1718 
1719 		default:
1720 			snprintf( c->cr_msg, sizeof( c->cr_msg),
1721 				"\"acl-authcDN <DN>\" incompatible "
1722 				"with auth method %d",
1723 				li->li_acl_authmethod );
1724 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1725 			return 1;
1726 		}
1727 		if ( !BER_BVISNULL( &li->li_acl_authcDN ) ) {
1728 			free( li->li_acl_authcDN.bv_val );
1729 		}
1730 		ber_memfree_x( c->value_dn.bv_val, NULL );
1731 		li->li_acl_authcDN = c->value_ndn;
1732 		BER_BVZERO( &c->value_dn );
1733 		BER_BVZERO( &c->value_ndn );
1734 		break;
1735 
1736 	case LDAP_BACK_CFG_ACL_PASSWD:
1737 		switch ( li->li_acl_authmethod ) {
1738 		case LDAP_AUTH_NONE:
1739 			li->li_acl_authmethod = LDAP_AUTH_SIMPLE;
1740 			break;
1741 
1742 		case LDAP_AUTH_SIMPLE:
1743 			break;
1744 
1745 		default:
1746 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
1747 				"\"acl-passwd <cred>\" incompatible "
1748 				"with auth method %d",
1749 				li->li_acl_authmethod );
1750 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1751 			return 1;
1752 		}
1753 		if ( !BER_BVISNULL( &li->li_acl_passwd ) ) {
1754 			free( li->li_acl_passwd.bv_val );
1755 		}
1756 		ber_str2bv( c->argv[ 1 ], 0, 1, &li->li_acl_passwd );
1757 		break;
1758 
1759 	case LDAP_BACK_CFG_ACL_METHOD:
1760 	case LDAP_BACK_CFG_ACL_BIND:
1761 		for ( i = 1; i < c->argc; i++ ) {
1762 			if ( bindconf_parse( c->argv[ i ], &li->li_acl ) ) {
1763 				return 1;
1764 			}
1765 		}
1766 		bindconf_tls_defaults( &li->li_acl );
1767 		break;
1768 
1769 	case LDAP_BACK_CFG_IDASSERT_MODE:
1770 		i = verb_to_mask( c->argv[1], idassert_mode );
1771 		if ( BER_BVISNULL( &idassert_mode[i].word ) ) {
1772 			if ( strncasecmp( c->argv[1], "u:", STRLENOF( "u:" ) ) == 0 ) {
1773 				li->li_idassert_mode = LDAP_BACK_IDASSERT_OTHERID;
1774 				ber_str2bv( c->argv[1], 0, 1, &li->li_idassert_authzID );
1775 				li->li_idassert_authzID.bv_val[ 0 ] = 'u';
1776 
1777 			} else {
1778 				struct berval	id, ndn;
1779 
1780 				ber_str2bv( c->argv[1], 0, 0, &id );
1781 
1782 				if ( strncasecmp( c->argv[1], "dn:", STRLENOF( "dn:" ) ) == 0 ) {
1783 					id.bv_val += STRLENOF( "dn:" );
1784 					id.bv_len -= STRLENOF( "dn:" );
1785 				}
1786 
1787 				rc = dnNormalize( 0, NULL, NULL, &id, &ndn, NULL );
1788                                 if ( rc != LDAP_SUCCESS ) {
1789                                         Debug( LDAP_DEBUG_ANY,
1790                                                 "%s: line %d: idassert ID \"%s\" is not a valid DN\n",
1791                                                 c->fname, c->lineno, c->argv[1] );
1792                                         return 1;
1793                                 }
1794 
1795                                 li->li_idassert_authzID.bv_len = STRLENOF( "dn:" ) + ndn.bv_len;
1796                                 li->li_idassert_authzID.bv_val = ch_malloc( li->li_idassert_authzID.bv_len + 1 );
1797                                 AC_MEMCPY( li->li_idassert_authzID.bv_val, "dn:", STRLENOF( "dn:" ) );
1798                                 AC_MEMCPY( &li->li_idassert_authzID.bv_val[ STRLENOF( "dn:" ) ], ndn.bv_val, ndn.bv_len + 1 );
1799                                 ch_free( ndn.bv_val );
1800 
1801                                 li->li_idassert_mode = LDAP_BACK_IDASSERT_OTHERDN;
1802 			}
1803 
1804 		} else {
1805 			li->li_idassert_mode = idassert_mode[i].mask;
1806 		}
1807 
1808 		if ( c->argc > 2 ) {
1809 			int	i;
1810 
1811 			for ( i = 2; i < c->argc; i++ ) {
1812 				if ( strcasecmp( c->argv[ i ], "override" ) == 0 ) {
1813 					li->li_idassert_flags |= LDAP_BACK_AUTH_OVERRIDE;
1814 
1815 				} else if ( strcasecmp( c->argv[ i ], "prescriptive" ) == 0 ) {
1816 					li->li_idassert_flags |= LDAP_BACK_AUTH_PRESCRIPTIVE;
1817 
1818 				} else if ( strcasecmp( c->argv[ i ], "non-prescriptive" ) == 0 ) {
1819 					li->li_idassert_flags &= ( ~LDAP_BACK_AUTH_PRESCRIPTIVE );
1820 
1821 				} else if ( strcasecmp( c->argv[ i ], "obsolete-proxy-authz" ) == 0 ) {
1822 					if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
1823 						Debug( LDAP_DEBUG_ANY,
1824                                        	 		"%s: line %d: \"obsolete-proxy-authz\" flag "
1825                                         		"in \"idassert-mode <args>\" "
1826                                         		"incompatible with previously issued \"obsolete-encoding-workaround\" flag.\n",
1827                                         		c->fname, c->lineno, 0 );
1828                                 		return 1;
1829 					}
1830 					li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ;
1831 
1832 				} else if ( strcasecmp( c->argv[ i ], "obsolete-encoding-workaround" ) == 0 ) {
1833 					if ( li->li_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
1834 						Debug( LDAP_DEBUG_ANY,
1835                                        	 		"%s: line %d: \"obsolete-encoding-workaround\" flag "
1836                                         		"in \"idassert-mode <args>\" "
1837                                         		"incompatible with previously issued \"obsolete-proxy-authz\" flag.\n",
1838                                         		c->fname, c->lineno, 0 );
1839                                 		return 1;
1840 					}
1841 					li->li_idassert_flags |= LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND;
1842 
1843 				} else {
1844 					Debug( LDAP_DEBUG_ANY,
1845                                         	"%s: line %d: unknown flag #%d "
1846                                         	"in \"idassert-mode <args> "
1847                                         	"[<flags>]\" line.\n",
1848                                         	c->fname, c->lineno, i - 2 );
1849                                 	return 1;
1850 				}
1851                         }
1852                 }
1853 		break;
1854 
1855 	case LDAP_BACK_CFG_IDASSERT_AUTHCDN:
1856 		switch ( li->li_idassert_authmethod ) {
1857 		case LDAP_AUTH_NONE:
1858 			li->li_idassert_authmethod = LDAP_AUTH_SIMPLE;
1859 			break;
1860 
1861 		case LDAP_AUTH_SIMPLE:
1862 			break;
1863 
1864 		default:
1865 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
1866 				"\"idassert-authcDN <DN>\" incompatible "
1867 				"with auth method %d",
1868 				li->li_idassert_authmethod );
1869 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1870 			return 1;
1871 		}
1872 		if ( !BER_BVISNULL( &li->li_idassert_authcDN ) ) {
1873 			free( li->li_idassert_authcDN.bv_val );
1874 		}
1875 		ber_memfree_x( c->value_dn.bv_val, NULL );
1876 		li->li_idassert_authcDN = c->value_ndn;
1877 		BER_BVZERO( &c->value_dn );
1878 		BER_BVZERO( &c->value_ndn );
1879 		break;
1880 
1881 	case LDAP_BACK_CFG_IDASSERT_PASSWD:
1882 		switch ( li->li_idassert_authmethod ) {
1883 		case LDAP_AUTH_NONE:
1884 			li->li_idassert_authmethod = LDAP_AUTH_SIMPLE;
1885 			break;
1886 
1887 		case LDAP_AUTH_SIMPLE:
1888 			break;
1889 
1890 		default:
1891 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
1892 				"\"idassert-passwd <cred>\" incompatible "
1893 				"with auth method %d",
1894 				li->li_idassert_authmethod );
1895 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1896 			return 1;
1897 		}
1898 		if ( !BER_BVISNULL( &li->li_idassert_passwd ) ) {
1899 			free( li->li_idassert_passwd.bv_val );
1900 		}
1901 		ber_str2bv( c->argv[ 1 ], 0, 1, &li->li_idassert_passwd );
1902 		break;
1903 
1904 	case LDAP_BACK_CFG_IDASSERT_AUTHZFROM:
1905 		rc = slap_idassert_authzfrom_parse( c, &li->li_idassert );
1906 		break;
1907 
1908 	case LDAP_BACK_CFG_IDASSERT_PASSTHRU:
1909 		rc = slap_idassert_passthru_parse( c, &li->li_idassert );
1910 		break;
1911 
1912 	case LDAP_BACK_CFG_IDASSERT_METHOD:
1913 		/* no longer supported */
1914 		snprintf( c->cr_msg, sizeof( c->cr_msg ),
1915 			"\"idassert-method <args>\": "
1916 			"no longer supported; use \"idassert-bind\"" );
1917 		Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1918 		return 1;
1919 
1920 	case LDAP_BACK_CFG_IDASSERT_BIND:
1921 		rc = slap_idassert_parse( c, &li->li_idassert );
1922 		break;
1923 
1924 	case LDAP_BACK_CFG_REBIND:
1925 		if ( c->argc == 1 || c->value_int ) {
1926 			li->li_flags |= LDAP_BACK_F_SAVECRED;
1927 
1928 		} else {
1929 			li->li_flags &= ~LDAP_BACK_F_SAVECRED;
1930 		}
1931 		break;
1932 
1933 	case LDAP_BACK_CFG_CHASE:
1934 		if ( c->argc == 1 || c->value_int ) {
1935 			li->li_flags |= LDAP_BACK_F_CHASE_REFERRALS;
1936 
1937 		} else {
1938 			li->li_flags &= ~LDAP_BACK_F_CHASE_REFERRALS;
1939 		}
1940 		break;
1941 
1942 	case LDAP_BACK_CFG_T_F: {
1943 		slap_mask_t		mask;
1944 
1945 		i = verb_to_mask( c->argv[1], t_f_mode );
1946 		if ( BER_BVISNULL( &t_f_mode[i].word ) ) {
1947 			return 1;
1948 		}
1949 
1950 		mask = t_f_mode[i].mask;
1951 
1952 		if ( LDAP_BACK_ISOPEN( li )
1953 			&& mask == LDAP_BACK_F_T_F_DISCOVER
1954 			&& !LDAP_BACK_T_F( li ) )
1955 		{
1956 			slap_bindconf	sb = { BER_BVNULL };
1957 			int		rc;
1958 
1959 			if ( li->li_uri == NULL ) {
1960 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
1961 					"need URI to discover absolute filters support "
1962 					"in \"t-f-support discover\"" );
1963 				Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1964 				return 1;
1965 			}
1966 
1967 			ber_str2bv( li->li_uri, 0, 0, &sb.sb_uri );
1968 			sb.sb_version = li->li_version;
1969 			sb.sb_method = LDAP_AUTH_SIMPLE;
1970 			BER_BVSTR( &sb.sb_binddn, "" );
1971 
1972 			rc = slap_discover_feature( &sb,
1973 					slap_schema.si_ad_supportedFeatures->ad_cname.bv_val,
1974 					LDAP_FEATURE_ABSOLUTE_FILTERS );
1975 			if ( rc == LDAP_COMPARE_TRUE ) {
1976 				mask |= LDAP_BACK_F_T_F;
1977 			}
1978 		}
1979 
1980 		li->li_flags &= ~LDAP_BACK_F_T_F_MASK2;
1981 		li->li_flags |= mask;
1982 		} break;
1983 
1984 	case LDAP_BACK_CFG_WHOAMI:
1985 		if ( c->argc == 1 || c->value_int ) {
1986 			li->li_flags |= LDAP_BACK_F_PROXY_WHOAMI;
1987 			load_extop( (struct berval *)&slap_EXOP_WHOAMI,
1988 					0, ldap_back_exop_whoami );
1989 
1990 		} else {
1991 			li->li_flags &= ~LDAP_BACK_F_PROXY_WHOAMI;
1992 		}
1993 		break;
1994 
1995 	case LDAP_BACK_CFG_TIMEOUT:
1996 		for ( i = 1; i < c->argc; i++ ) {
1997 			if ( isdigit( (unsigned char) c->argv[ i ][ 0 ] ) ) {
1998 				int		j;
1999 				unsigned	u;
2000 
2001 				if ( lutil_atoux( &u, c->argv[ i ], 0 ) != 0 ) {
2002 					snprintf( c->cr_msg, sizeof( c->cr_msg),
2003 						"unable to parse timeout \"%s\"",
2004 						c->argv[ i ] );
2005 					Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2006 					return 1;
2007 				}
2008 
2009 				for ( j = 0; j < SLAP_OP_LAST; j++ ) {
2010 					li->li_timeout[ j ] = u;
2011 				}
2012 
2013 				continue;
2014 			}
2015 
2016 			if ( slap_cf_aux_table_parse( c->argv[ i ], li->li_timeout, timeout_table, "slapd-ldap timeout" ) ) {
2017 				snprintf( c->cr_msg, sizeof( c->cr_msg),
2018 					"unable to parse timeout \"%s\"",
2019 					c->argv[ i ] );
2020 				Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2021 				return 1;
2022 			}
2023 		}
2024 		break;
2025 
2026 	case LDAP_BACK_CFG_IDLE_TIMEOUT: {
2027 		unsigned long	t;
2028 
2029 		if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
2030 			snprintf( c->cr_msg, sizeof( c->cr_msg),
2031 				"unable to parse idle timeout \"%s\"",
2032 				c->argv[ 1 ] );
2033 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2034 			return 1;
2035 		}
2036 		li->li_idle_timeout = (time_t)t;
2037 		} break;
2038 
2039 	case LDAP_BACK_CFG_CONN_TTL: {
2040 		unsigned long	t;
2041 
2042 		if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
2043 			snprintf( c->cr_msg, sizeof( c->cr_msg),
2044 				"unable to parse conn ttl\"%s\"",
2045 				c->argv[ 1 ] );
2046 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2047 			return 1;
2048 		}
2049 		li->li_conn_ttl = (time_t)t;
2050 		} break;
2051 
2052 	case LDAP_BACK_CFG_NETWORK_TIMEOUT: {
2053 		unsigned long	t;
2054 
2055 		if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
2056 			snprintf( c->cr_msg, sizeof( c->cr_msg),
2057 				"unable to parse network timeout \"%s\"",
2058 				c->argv[ 1 ] );
2059 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2060 			return 1;
2061 		}
2062 		li->li_network_timeout = (time_t)t;
2063 		} break;
2064 
2065 	case LDAP_BACK_CFG_VERSION:
2066 		if ( c->value_int != 0 && ( c->value_int < LDAP_VERSION_MIN || c->value_int > LDAP_VERSION_MAX ) ) {
2067 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
2068 				"unsupported version \"%s\" "
2069 				"in \"protocol-version <version>\"",
2070 				c->argv[ 1 ] );
2071 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2072 			return 1;
2073 		}
2074 
2075 		li->li_version = c->value_int;
2076 		break;
2077 
2078 	case LDAP_BACK_CFG_SINGLECONN:
2079 		if ( c->value_int ) {
2080 			li->li_flags |= LDAP_BACK_F_SINGLECONN;
2081 
2082 		} else {
2083 			li->li_flags &= ~LDAP_BACK_F_SINGLECONN;
2084 		}
2085 		break;
2086 
2087 	case LDAP_BACK_CFG_USETEMP:
2088 		if ( c->value_int ) {
2089 			li->li_flags |= LDAP_BACK_F_USE_TEMPORARIES;
2090 
2091 		} else {
2092 			li->li_flags &= ~LDAP_BACK_F_USE_TEMPORARIES;
2093 		}
2094 		break;
2095 
2096 	case LDAP_BACK_CFG_CONNPOOLMAX:
2097 		if ( c->value_int < LDAP_BACK_CONN_PRIV_MIN
2098 			|| c->value_int > LDAP_BACK_CONN_PRIV_MAX )
2099 		{
2100 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
2101 				"invalid max size " "of privileged "
2102 				"connections pool \"%s\" "
2103 				"in \"conn-pool-max <n> "
2104 				"(must be between %d and %d)\"",
2105 				c->argv[ 1 ],
2106 				LDAP_BACK_CONN_PRIV_MIN,
2107 				LDAP_BACK_CONN_PRIV_MAX );
2108 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2109 			return 1;
2110 		}
2111 		li->li_conn_priv_max = c->value_int;
2112 		break;
2113 
2114 	case LDAP_BACK_CFG_CANCEL: {
2115 		slap_mask_t		mask;
2116 
2117 		i = verb_to_mask( c->argv[1], cancel_mode );
2118 		if ( BER_BVISNULL( &cancel_mode[i].word ) ) {
2119 			return 1;
2120 		}
2121 
2122 		mask = cancel_mode[i].mask;
2123 
2124 		if ( LDAP_BACK_ISOPEN( li )
2125 			&& mask == LDAP_BACK_F_CANCEL_EXOP_DISCOVER
2126 			&& !LDAP_BACK_CANCEL( li ) )
2127 		{
2128 			slap_bindconf	sb = { BER_BVNULL };
2129 			int		rc;
2130 
2131 			if ( li->li_uri == NULL ) {
2132 				snprintf( c->cr_msg, sizeof( c->cr_msg ),
2133 					"need URI to discover \"cancel\" support "
2134 					"in \"cancel exop-discover\"" );
2135 				Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2136 				return 1;
2137 			}
2138 
2139 			ber_str2bv( li->li_uri, 0, 0, &sb.sb_uri );
2140 			sb.sb_version = li->li_version;
2141 			sb.sb_method = LDAP_AUTH_SIMPLE;
2142 			BER_BVSTR( &sb.sb_binddn, "" );
2143 
2144 			rc = slap_discover_feature( &sb,
2145 					slap_schema.si_ad_supportedExtension->ad_cname.bv_val,
2146 					LDAP_EXOP_CANCEL );
2147 			if ( rc == LDAP_COMPARE_TRUE ) {
2148 				mask |= LDAP_BACK_F_CANCEL_EXOP;
2149 			}
2150 		}
2151 
2152 		li->li_flags &= ~LDAP_BACK_F_CANCEL_MASK2;
2153 		li->li_flags |= mask;
2154 		} break;
2155 
2156 	case LDAP_BACK_CFG_QUARANTINE:
2157 		if ( LDAP_BACK_QUARANTINE( li ) ) {
2158 			snprintf( c->cr_msg, sizeof( c->cr_msg ),
2159 				"quarantine already defined" );
2160 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2161 			return 1;
2162 		}
2163 		rc = slap_retry_info_parse( c->argv[1], &li->li_quarantine,
2164 			c->cr_msg, sizeof( c->cr_msg ) );
2165 		if ( rc ) {
2166 			Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2167 
2168 		} else {
2169 			ldap_pvt_thread_mutex_init( &li->li_quarantine_mutex );
2170 			/* give it a chance to retry if the pattern gets reset
2171 			 * via back-config */
2172 			li->li_isquarantined = 0;
2173 			li->li_flags |= LDAP_BACK_F_QUARANTINE;
2174 		}
2175 		break;
2176 
2177 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
2178 	case LDAP_BACK_CFG_ST_REQUEST:
2179 		if ( c->value_int ) {
2180 			li->li_flags |= LDAP_BACK_F_ST_REQUEST;
2181 
2182 		} else {
2183 			li->li_flags &= ~LDAP_BACK_F_ST_REQUEST;
2184 		}
2185 		break;
2186 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
2187 
2188 	case LDAP_BACK_CFG_NOREFS:
2189 		if ( c->value_int ) {
2190 			li->li_flags |= LDAP_BACK_F_NOREFS;
2191 
2192 		} else {
2193 			li->li_flags &= ~LDAP_BACK_F_NOREFS;
2194 		}
2195 		break;
2196 
2197 	case LDAP_BACK_CFG_NOUNDEFFILTER:
2198 		if ( c->value_int ) {
2199 			li->li_flags |= LDAP_BACK_F_NOUNDEFFILTER;
2200 
2201 		} else {
2202 			li->li_flags &= ~LDAP_BACK_F_NOUNDEFFILTER;
2203 		}
2204 		break;
2205 
2206 	case LDAP_BACK_CFG_REWRITE:
2207 		snprintf( c->cr_msg, sizeof( c->cr_msg ),
2208 			"rewrite/remap capabilities have been moved "
2209 			"to the \"rwm\" overlay; see slapo-rwm(5) "
2210 			"for details (hint: add \"overlay rwm\" "
2211 			"and prefix all directives with \"rwm-\")" );
2212 		Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2213 		return 1;
2214 
2215 	default:
2216 		/* FIXME: try to catch inconsistencies */
2217 		assert( 0 );
2218 		break;
2219 	}
2220 
2221 	return rc;
2222 }
2223 
2224 int
2225 ldap_back_init_cf( BackendInfo *bi )
2226 {
2227 	int			rc;
2228 	AttributeDescription	*ad = NULL;
2229 	const char		*text;
2230 
2231 	/* Make sure we don't exceed the bits reserved for userland */
2232 	config_check_userland( LDAP_BACK_CFG_LAST );
2233 
2234 	bi->bi_cf_ocs = ldapocs;
2235 
2236 	rc = config_register_schema( ldapcfg, ldapocs );
2237 	if ( rc ) {
2238 		return rc;
2239 	}
2240 
2241 	/* setup olcDbAclPasswd and olcDbIDAssertPasswd
2242 	 * to be base64-encoded when written in LDIF form;
2243 	 * basically, we don't care if it fails */
2244 	rc = slap_str2ad( "olcDbACLPasswd", &ad, &text );
2245 	if ( rc ) {
2246 		Debug( LDAP_DEBUG_ANY, "config_back_initialize: "
2247 			"warning, unable to get \"olcDbACLPasswd\" "
2248 			"attribute description: %d: %s\n",
2249 			rc, text, 0 );
2250 	} else {
2251 		(void)ldif_must_b64_encode_register( ad->ad_cname.bv_val,
2252 			ad->ad_type->sat_oid );
2253 	}
2254 
2255 	ad = NULL;
2256 	rc = slap_str2ad( "olcDbIDAssertPasswd", &ad, &text );
2257 	if ( rc ) {
2258 		Debug( LDAP_DEBUG_ANY, "config_back_initialize: "
2259 			"warning, unable to get \"olcDbIDAssertPasswd\" "
2260 			"attribute description: %d: %s\n",
2261 			rc, text, 0 );
2262 	} else {
2263 		(void)ldif_must_b64_encode_register( ad->ad_cname.bv_val,
2264 			ad->ad_type->sat_oid );
2265 	}
2266 
2267 	return 0;
2268 }
2269 
2270 static int
2271 ldap_pbind_cf_gen( ConfigArgs *c )
2272 {
2273 	slap_overinst	*on = (slap_overinst *)c->bi;
2274 	void	*private = c->be->be_private;
2275 	int		rc;
2276 
2277 	c->be->be_private = on->on_bi.bi_private;
2278 	rc = ldap_back_cf_gen( c );
2279 	c->be->be_private = private;
2280 	return rc;
2281 }
2282 
2283 int
2284 ldap_pbind_init_cf( BackendInfo *bi )
2285 {
2286 	bi->bi_cf_ocs = pbindocs;
2287 
2288 	return config_register_schema( pbindcfg, pbindocs );
2289 }
2290 
2291 static int
2292 ldap_back_exop_whoami(
2293 		Operation	*op,
2294 		SlapReply	*rs )
2295 {
2296 	struct berval *bv = NULL;
2297 
2298 	if ( op->oq_extended.rs_reqdata != NULL ) {
2299 		/* no request data should be provided */
2300 		rs->sr_text = "no request data expected";
2301 		return rs->sr_err = LDAP_PROTOCOL_ERROR;
2302 	}
2303 
2304 	Statslog( LDAP_DEBUG_STATS, "%s WHOAMI\n",
2305 	    op->o_log_prefix, 0, 0, 0, 0 );
2306 
2307 	rs->sr_err = backend_check_restrictions( op, rs,
2308 			(struct berval *)&slap_EXOP_WHOAMI );
2309 	if( rs->sr_err != LDAP_SUCCESS ) return rs->sr_err;
2310 
2311 	/* if auth'd by back-ldap and request is proxied, forward it */
2312 	if ( op->o_conn->c_authz_backend
2313 		&& !strcmp( op->o_conn->c_authz_backend->be_type, "ldap" )
2314 		&& !dn_match( &op->o_ndn, &op->o_conn->c_ndn ) )
2315 	{
2316 		ldapconn_t	*lc = NULL;
2317 		LDAPControl c, *ctrls[2] = {NULL, NULL};
2318 		LDAPMessage *res;
2319 		Operation op2 = *op;
2320 		ber_int_t msgid;
2321 		int doretry = 1;
2322 		char *ptr;
2323 
2324 		ctrls[0] = &c;
2325 		op2.o_ndn = op->o_conn->c_ndn;
2326 		if ( !ldap_back_dobind( &lc, &op2, rs, LDAP_BACK_SENDERR ) ) {
2327 			return -1;
2328 		}
2329 		c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
2330 		c.ldctl_iscritical = 1;
2331 		c.ldctl_value.bv_val = op->o_tmpalloc(
2332 			op->o_ndn.bv_len + STRLENOF( "dn:" ) + 1,
2333 			op->o_tmpmemctx );
2334 		c.ldctl_value.bv_len = op->o_ndn.bv_len + 3;
2335 		ptr = c.ldctl_value.bv_val;
2336 		ptr = lutil_strcopy( ptr, "dn:" );
2337 		ptr = lutil_strncopy( ptr, op->o_ndn.bv_val, op->o_ndn.bv_len );
2338 		ptr[ 0 ] = '\0';
2339 
2340 retry:
2341 		rs->sr_err = ldap_whoami( lc->lc_ld, ctrls, NULL, &msgid );
2342 		if ( rs->sr_err == LDAP_SUCCESS ) {
2343 			/* by now, make sure no timeout is used (ITS#6282) */
2344 			struct timeval tv;
2345 			tv.tv_sec = -1;
2346 			if ( ldap_result( lc->lc_ld, msgid, LDAP_MSG_ALL, &tv, &res ) == -1 ) {
2347 				ldap_get_option( lc->lc_ld, LDAP_OPT_ERROR_NUMBER,
2348 					&rs->sr_err );
2349 				if ( rs->sr_err == LDAP_SERVER_DOWN && doretry ) {
2350 					doretry = 0;
2351 					if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) {
2352 						goto retry;
2353 					}
2354 				}
2355 
2356 			} else {
2357 				/* NOTE: are we sure "bv" will be malloc'ed
2358 				 * with the appropriate memory? */
2359 				rs->sr_err = ldap_parse_whoami( lc->lc_ld, res, &bv );
2360 				ldap_msgfree(res);
2361 			}
2362 		}
2363 		op->o_tmpfree( c.ldctl_value.bv_val, op->o_tmpmemctx );
2364 		if ( rs->sr_err != LDAP_SUCCESS ) {
2365 			rs->sr_err = slap_map_api2result( rs );
2366 		}
2367 
2368 		if ( lc != NULL ) {
2369 			ldap_back_release_conn( (ldapinfo_t *)op2.o_bd->be_private, lc );
2370 		}
2371 
2372 	} else {
2373 		/* else just do the same as before */
2374 		bv = (struct berval *) ch_malloc( sizeof( struct berval ) );
2375 		if ( !BER_BVISEMPTY( &op->o_dn ) ) {
2376 			bv->bv_len = op->o_dn.bv_len + STRLENOF( "dn:" );
2377 			bv->bv_val = ch_malloc( bv->bv_len + 1 );
2378 			AC_MEMCPY( bv->bv_val, "dn:", STRLENOF( "dn:" ) );
2379 			AC_MEMCPY( &bv->bv_val[ STRLENOF( "dn:" ) ], op->o_dn.bv_val,
2380 				op->o_dn.bv_len );
2381 			bv->bv_val[ bv->bv_len ] = '\0';
2382 
2383 		} else {
2384 			bv->bv_len = 0;
2385 			bv->bv_val = NULL;
2386 		}
2387 	}
2388 
2389 	rs->sr_rspdata = bv;
2390 	return rs->sr_err;
2391 }
2392 
2393 
2394