1 /* $NetBSD: config.c,v 1.2 2021/08/14 16:14:59 christos Exp $ */
2
3 /* config.c - configuration parsing for back-asyncmeta */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 2016-2021 The OpenLDAP Foundation.
8 * Portions Copyright 2016 Symas Corporation.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted only as authorized by the OpenLDAP
13 * Public License.
14 *
15 * A copy of this license is available in the file LICENSE in the
16 * top-level directory of the distribution or, alternatively, at
17 * <http://www.OpenLDAP.org/license.html>.
18 */
19
20 /* ACKNOWLEDGEMENTS:
21 * This work was developed by Symas Corporation
22 * based on back-meta module for inclusion in OpenLDAP Software.
23 * This work was sponsored by Ericsson. */
24
25 #include <sys/cdefs.h>
26 __RCSID("$NetBSD: config.c,v 1.2 2021/08/14 16:14:59 christos Exp $");
27
28 #include "portable.h"
29
30 #include <stdio.h>
31 #include <ctype.h>
32
33 #include <ac/string.h>
34 #include <ac/socket.h>
35
36 #include "slap.h"
37 #include "slap-config.h"
38 #include "lutil.h"
39 #include "ldif.h"
40 #include "../back-ldap/back-ldap.h"
41 #include "back-asyncmeta.h"
42
43 #ifdef LDAP_DEVEL
44 #define SLAP_AUTH_DN 1
45 #endif
46
47 static ConfigDriver asyncmeta_back_cf_gen;
48 static ConfigLDAPadd asyncmeta_ldadd;
49 static ConfigCfAdd asyncmeta_cfadd;
50
51 /* Three sets of enums:
52 * 1) attrs that are only valid in the base config
53 * 2) attrs that are valid in base or target
54 * 3) attrs that are only valid in a target
55 */
56
57 /* Base attrs */
58 enum {
59 LDAP_BACK_CFG_DNCACHE_TTL = 1,
60 LDAP_BACK_CFG_IDLE_TIMEOUT,
61 LDAP_BACK_CFG_ONERR,
62 LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER,
63 LDAP_BACK_CFG_CONNPOOLMAX,
64 LDAP_BACK_CFG_MAX_TIMEOUT_OPS,
65 LDAP_BACK_CFG_MAX_PENDING_OPS,
66 LDAP_BACK_CFG_MAX_TARGET_CONNS,
67 LDAP_BACK_CFG_LAST_BASE,
68 };
69
70 /* Base or target */
71 enum {
72 LDAP_BACK_CFG_BIND_TIMEOUT = LDAP_BACK_CFG_LAST_BASE,
73 LDAP_BACK_CFG_CANCEL,
74 LDAP_BACK_CFG_CHASE,
75 LDAP_BACK_CFG_CLIENT_PR,
76 LDAP_BACK_CFG_DEFAULT_T,
77 LDAP_BACK_CFG_NETWORK_TIMEOUT,
78 LDAP_BACK_CFG_NOREFS,
79 LDAP_BACK_CFG_NOUNDEFFILTER,
80 LDAP_BACK_CFG_NRETRIES,
81 LDAP_BACK_CFG_QUARANTINE,
82 LDAP_BACK_CFG_REBIND,
83 LDAP_BACK_CFG_TIMEOUT,
84 LDAP_BACK_CFG_VERSION,
85 LDAP_BACK_CFG_ST_REQUEST,
86 LDAP_BACK_CFG_T_F,
87 LDAP_BACK_CFG_TLS,
88 LDAP_BACK_CFG_LAST_BOTH
89 };
90
91 /* Target attrs */
92 enum {
93 LDAP_BACK_CFG_URI = LDAP_BACK_CFG_LAST_BOTH,
94 LDAP_BACK_CFG_IDASSERT_AUTHZFROM,
95 LDAP_BACK_CFG_IDASSERT_BIND,
96 LDAP_BACK_CFG_SUFFIXM,
97 LDAP_BACK_CFG_SUBTREE_EX,
98 LDAP_BACK_CFG_SUBTREE_IN,
99 LDAP_BACK_CFG_KEEPALIVE,
100 LDAP_BACK_CFG_FILTER,
101 LDAP_BACK_CFG_TCP_USER_TIMEOUT,
102 LDAP_BACK_CFG_LAST
103 };
104
105 static ConfigTable a_metacfg[] = {
106 { "uri", "uri", 2, 0, 0,
107 ARG_MAGIC|LDAP_BACK_CFG_URI,
108 asyncmeta_back_cf_gen, "( OLcfgDbAt:0.14 "
109 "NAME 'olcDbURI' "
110 "DESC 'URI (list) for remote DSA' "
111 "SYNTAX OMsDirectoryString "
112 "SINGLE-VALUE )",
113 NULL, NULL },
114 { "tls", "what", 2, 0, 0,
115 ARG_MAGIC|LDAP_BACK_CFG_TLS,
116 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.1 "
117 "NAME 'olcDbStartTLS' "
118 "DESC 'StartTLS' "
119 "SYNTAX OMsDirectoryString "
120 "SINGLE-VALUE )",
121 NULL, NULL },
122 { "idassert-bind", "args", 2, 0, 0,
123 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND,
124 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.7 "
125 "NAME 'olcDbIDAssertBind' "
126 "DESC 'Remote Identity Assertion administrative identity auth bind configuration' "
127 "SYNTAX OMsDirectoryString "
128 "SINGLE-VALUE )",
129 NULL, NULL },
130 { "idassert-authzFrom", "authzRule", 2, 2, 0,
131 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHZFROM,
132 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.9 "
133 "NAME 'olcDbIDAssertAuthzFrom' "
134 "DESC 'Remote Identity Assertion authz rules' "
135 "EQUALITY caseIgnoreMatch "
136 "SYNTAX OMsDirectoryString "
137 "X-ORDERED 'VALUES' )",
138 NULL, NULL },
139 { "rebind-as-user", "true|FALSE", 1, 2, 0,
140 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND,
141 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.10 "
142 "NAME 'olcDbRebindAsUser' "
143 "DESC 'Rebind as user' "
144 "SYNTAX OMsBoolean "
145 "SINGLE-VALUE )",
146 NULL, NULL },
147 { "chase-referrals", "true|FALSE", 2, 2, 0,
148 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE,
149 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.11 "
150 "NAME 'olcDbChaseReferrals' "
151 "DESC 'Chase referrals' "
152 "SYNTAX OMsBoolean "
153 "SINGLE-VALUE )",
154 NULL, NULL },
155 { "t-f-support", "true|FALSE|discover", 2, 2, 0,
156 ARG_MAGIC|LDAP_BACK_CFG_T_F,
157 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.12 "
158 "NAME 'olcDbTFSupport' "
159 "DESC 'Absolute filters support' "
160 "SYNTAX OMsDirectoryString "
161 "SINGLE-VALUE )",
162 NULL, NULL },
163 { "timeout", "timeout(list)", 2, 0, 0,
164 ARG_MAGIC|LDAP_BACK_CFG_TIMEOUT,
165 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.14 "
166 "NAME 'olcDbTimeout' "
167 "DESC 'Per-operation timeouts' "
168 "SYNTAX OMsDirectoryString "
169 "SINGLE-VALUE )",
170 NULL, NULL },
171 { "idle-timeout", "timeout", 2, 2, 0,
172 ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT,
173 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.15 "
174 "NAME 'olcDbIdleTimeout' "
175 "DESC 'connection idle timeout' "
176 "SYNTAX OMsDirectoryString "
177 "SINGLE-VALUE )",
178 NULL, NULL },
179 { "network-timeout", "timeout", 2, 2, 0,
180 ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT,
181 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.17 "
182 "NAME 'olcDbNetworkTimeout' "
183 "DESC 'connection network timeout' "
184 "SYNTAX OMsDirectoryString "
185 "SINGLE-VALUE )",
186 NULL, NULL },
187 { "protocol-version", "version", 2, 2, 0,
188 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION,
189 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.18 "
190 "NAME 'olcDbProtocolVersion' "
191 "DESC 'protocol version' "
192 "SYNTAX OMsInteger "
193 "SINGLE-VALUE )",
194 NULL, NULL },
195
196 { "cancel", "ABANDON|ignore|exop", 2, 2, 0,
197 ARG_MAGIC|LDAP_BACK_CFG_CANCEL,
198 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.20 "
199 "NAME 'olcDbCancel' "
200 "DESC 'abandon/ignore/exop operations when appropriate' "
201 "SYNTAX OMsDirectoryString "
202 "SINGLE-VALUE )",
203 NULL, NULL },
204 { "quarantine", "retrylist", 2, 2, 0,
205 ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE,
206 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.21 "
207 "NAME 'olcDbQuarantine' "
208 "DESC 'Quarantine database if connection fails and retry according to rule' "
209 "SYNTAX OMsDirectoryString "
210 "SINGLE-VALUE )",
211 NULL, NULL },
212
213 { "conn-pool-max", "<n>", 2, 2, 0,
214 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX,
215 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.23 "
216 "NAME 'olcDbConnectionPoolMax' "
217 "DESC 'Max size of privileged connections pool' "
218 "SYNTAX OMsInteger "
219 "SINGLE-VALUE )",
220 NULL, NULL },
221 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
222 { "session-tracking-request", "true|FALSE", 2, 2, 0,
223 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_ST_REQUEST,
224 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.24 "
225 "NAME 'olcDbSessionTrackingRequest' "
226 "DESC 'Add session tracking control to proxied requests' "
227 "SYNTAX OMsBoolean "
228 "SINGLE-VALUE )",
229 NULL, NULL },
230 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
231 { "norefs", "true|FALSE", 2, 2, 0,
232 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOREFS,
233 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.25 "
234 "NAME 'olcDbNoRefs' "
235 "DESC 'Do not return search reference responses' "
236 "SYNTAX OMsBoolean "
237 "SINGLE-VALUE )",
238 NULL, NULL },
239 { "noundeffilter", "true|FALSE", 2, 2, 0,
240 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOUNDEFFILTER,
241 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.26 "
242 "NAME 'olcDbNoUndefFilter' "
243 "DESC 'Do not propagate undefined search filters' "
244 "SYNTAX OMsBoolean "
245 "SINGLE-VALUE )",
246 NULL, NULL },
247
248 { "suffixmassage", "local> <remote", 2, 3, 0,
249 ARG_MAGIC|LDAP_BACK_CFG_SUFFIXM,
250 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.117 "
251 "NAME 'olcDbSuffixMassage' "
252 "DESC 'DN suffix massage' "
253 "EQUALITY caseIgnoreMatch "
254 "SYNTAX OMsDirectoryString "
255 "SINGLE-VALUE )",
256 NULL, NULL },
257
258 { "subtree-exclude", "pattern", 2, 2, 0,
259 ARG_MAGIC|LDAP_BACK_CFG_SUBTREE_EX,
260 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.103 "
261 "NAME 'olcDbSubtreeExclude' "
262 "DESC 'DN of subtree to exclude from target' "
263 "EQUALITY caseIgnoreMatch "
264 "SYNTAX OMsDirectoryString )",
265 NULL, NULL },
266 { "subtree-include", "pattern", 2, 2, 0,
267 ARG_MAGIC|LDAP_BACK_CFG_SUBTREE_IN,
268 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.104 "
269 "NAME 'olcDbSubtreeInclude' "
270 "DESC 'DN of subtree to include in target' "
271 "EQUALITY caseIgnoreMatch "
272 "SYNTAX OMsDirectoryString )",
273 NULL, NULL },
274 { "default-target", "[none|<target ID>]", 1, 2, 0,
275 ARG_MAGIC|LDAP_BACK_CFG_DEFAULT_T,
276 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.105 "
277 "NAME 'olcDbDefaultTarget' "
278 "DESC 'Specify the default target' "
279 "SYNTAX OMsDirectoryString "
280 "SINGLE-VALUE )",
281 NULL, NULL },
282 { "dncache-ttl", "ttl", 2, 2, 0,
283 ARG_MAGIC|LDAP_BACK_CFG_DNCACHE_TTL,
284 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.106 "
285 "NAME 'olcDbDnCacheTtl' "
286 "DESC 'dncache ttl' "
287 "SYNTAX OMsDirectoryString "
288 "SINGLE-VALUE )",
289 NULL, NULL },
290 { "bind-timeout", "microseconds", 2, 2, 0,
291 ARG_MAGIC|ARG_ULONG|LDAP_BACK_CFG_BIND_TIMEOUT,
292 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.107 "
293 "NAME 'olcDbBindTimeout' "
294 "DESC 'bind timeout' "
295 "SYNTAX OMsDirectoryString "
296 "SINGLE-VALUE )",
297 NULL, NULL },
298 { "onerr", "CONTINUE|report|stop", 2, 2, 0,
299 ARG_MAGIC|LDAP_BACK_CFG_ONERR,
300 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.108 "
301 "NAME 'olcDbOnErr' "
302 "DESC 'error handling' "
303 "SYNTAX OMsDirectoryString "
304 "SINGLE-VALUE )",
305 NULL, NULL },
306 { "pseudoroot-bind-defer", "TRUE|false", 2, 2, 0,
307 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER,
308 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.109 "
309 "NAME 'olcDbPseudoRootBindDefer' "
310 "DESC 'error handling' "
311 "SYNTAX OMsBoolean "
312 "SINGLE-VALUE )",
313 NULL, NULL },
314 { "root-bind-defer", "TRUE|false", 2, 2, 0,
315 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER,
316 asyncmeta_back_cf_gen, NULL, NULL, NULL },
317 { "nretries", "NEVER|forever|<number>", 2, 2, 0,
318 ARG_MAGIC|LDAP_BACK_CFG_NRETRIES,
319 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.110 "
320 "NAME 'olcDbNretries' "
321 "DESC 'retry handling' "
322 "SYNTAX OMsDirectoryString "
323 "SINGLE-VALUE )",
324 NULL, NULL },
325 { "client-pr", "accept-unsolicited|disable|<size>", 2, 2, 0,
326 ARG_MAGIC|LDAP_BACK_CFG_CLIENT_PR,
327 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.111 "
328 "NAME 'olcDbClientPr' "
329 "DESC 'PagedResults handling' "
330 "SYNTAX OMsDirectoryString "
331 "SINGLE-VALUE )",
332 NULL, NULL },
333
334 { "", "", 0, 0, 0, ARG_IGNORED,
335 NULL, "( OLcfgDbAt:3.116 NAME 'olcAsyncMetaSub' "
336 "DESC 'Placeholder to name a Target entry' "
337 "EQUALITY caseIgnoreMatch "
338 "SYNTAX OMsDirectoryString "
339 "SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL },
340
341 { "keepalive", "keepalive", 2, 2, 0,
342 ARG_MAGIC|LDAP_BACK_CFG_KEEPALIVE,
343 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.29 "
344 "NAME 'olcDbKeepalive' "
345 "DESC 'TCP keepalive' "
346 "SYNTAX OMsDirectoryString "
347 "SINGLE-VALUE )",
348 NULL, NULL },
349
350 { "tcp-user-timeout", "milliseconds", 2, 2, 0,
351 ARG_MAGIC|ARG_UINT|LDAP_BACK_CFG_TCP_USER_TIMEOUT,
352 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.30 "
353 "NAME 'olcDbTcpUserTimeout' "
354 "DESC 'TCP User Timeout' "
355 "SYNTAX OMsInteger "
356 "SINGLE-VALUE )",
357 NULL, NULL },
358
359 { "filter", "pattern", 2, 2, 0,
360 ARG_MAGIC|LDAP_BACK_CFG_FILTER,
361 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.112 "
362 "NAME 'olcDbFilter' "
363 "DESC 'Filter regex pattern to include in target' "
364 "EQUALITY caseExactMatch "
365 "SYNTAX OMsDirectoryString )",
366 NULL, NULL },
367
368 { "max-pending-ops", "<n>", 2, 2, 0,
369 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_MAX_PENDING_OPS,
370 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.113 "
371 "NAME 'olcDbMaxPendingOps' "
372 "DESC 'Maximum number of pending operations' "
373 "SYNTAX OMsInteger "
374 "SINGLE-VALUE )",
375 NULL, NULL },
376
377 { "max-target-conns", "<n>", 2, 2, 0,
378 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_MAX_TARGET_CONNS,
379 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.114 "
380 "NAME 'olcDbMaxTargetConns' "
381 "DESC 'Maximum number of open connections per target' "
382 "SYNTAX OMsInteger "
383 "SINGLE-VALUE )",
384 NULL, NULL },
385
386 { "max-timeout-ops", "<n>", 2, 2, 0,
387 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_MAX_TIMEOUT_OPS,
388 asyncmeta_back_cf_gen, "( OLcfgDbAt:3.115 "
389 "NAME 'olcDbMaxTimeoutOps' "
390 "DESC 'Maximum number of consecutive timeout operations after which the connection is reset' "
391 "SYNTAX OMsInteger "
392 "SINGLE-VALUE )",
393 NULL, NULL },
394
395 { NULL, NULL, 0, 0, 0, ARG_IGNORED,
396 NULL, NULL, NULL, NULL }
397 };
398
399 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
400 #define ST_ATTR "$ olcDbSessionTrackingRequest "
401 #else
402 #define ST_ATTR ""
403 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
404
405 #define COMMON_ATTRS \
406 "$ olcDbBindTimeout " \
407 "$ olcDbCancel " \
408 "$ olcDbChaseReferrals " \
409 "$ olcDbClientPr " \
410 "$ olcDbDefaultTarget " \
411 "$ olcDbNetworkTimeout " \
412 "$ olcDbNoRefs " \
413 "$ olcDbNoUndefFilter " \
414 "$ olcDbNretries " \
415 "$ olcDbProtocolVersion " \
416 "$ olcDbQuarantine " \
417 "$ olcDbRebindAsUser " \
418 ST_ATTR \
419 "$ olcDbStartTLS " \
420 "$ olcDbTFSupport "
421
422 static ConfigOCs a_metaocs[] = {
423 { "( OLcfgDbOc:3.4 "
424 "NAME 'olcAsyncMetaConfig' "
425 "DESC 'Asyncmeta backend configuration' "
426 "SUP olcDatabaseConfig "
427 "MAY ( olcDbDnCacheTtl "
428 "$ olcDbIdleTimeout "
429 "$ olcDbOnErr "
430 "$ olcDbPseudoRootBindDefer "
431 "$ olcDbConnectionPoolMax "
432 "$ olcDbMaxTimeoutOps"
433 "$ olcDbMaxPendingOps "
434 "$ olcDbMaxTargetConns"
435 /* defaults, may be overridden per-target */
436 COMMON_ATTRS
437 ") )",
438 Cft_Database, a_metacfg, NULL, asyncmeta_cfadd },
439 { "( OLcfgDbOc:3.5 "
440 "NAME 'olcAsyncMetaTargetConfig' "
441 "DESC 'Asyncmeta target configuration' "
442 "SUP olcConfig STRUCTURAL "
443 "MUST ( olcAsyncMetaSub $ olcDbURI ) "
444 "MAY ( olcDbIDAssertAuthzFrom "
445 "$ olcDbIDAssertBind "
446 "$ olcDbSuffixMassage "
447 "$ olcDbSubtreeExclude "
448 "$ olcDbSubtreeInclude "
449 "$ olcDbTimeout "
450 "$ olcDbKeepalive "
451 "$ olcDbFilter "
452 "$ olcDbTcpUserTimeout "
453
454 /* defaults may be inherited */
455 COMMON_ATTRS
456 ") )",
457 Cft_Misc, a_metacfg, asyncmeta_ldadd },
458 { NULL, 0, NULL }
459 };
460
461 static int
asyncmeta_ldadd(CfEntryInfo * p,Entry * e,ConfigArgs * c)462 asyncmeta_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *c )
463 {
464 if ( p->ce_type != Cft_Database || !p->ce_be ||
465 p->ce_be->be_cf_ocs != a_metaocs )
466 return LDAP_CONSTRAINT_VIOLATION;
467
468 c->be = p->ce_be;
469 return LDAP_SUCCESS;
470 }
471
472 static int
asyncmeta_cfadd(Operation * op,SlapReply * rs,Entry * p,ConfigArgs * c)473 asyncmeta_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *c )
474 {
475 a_metainfo_t *mi = ( a_metainfo_t * )c->be->be_private;
476 struct berval bv;
477 int i;
478
479 bv.bv_val = c->cr_msg;
480 for ( i=0; i<mi->mi_ntargets; i++ ) {
481 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg),
482 "olcAsyncMetaSub=" SLAP_X_ORDERED_FMT "uri", i );
483 c->ca_private = mi->mi_targets[i];
484 c->valx = i;
485 config_build_entry( op, rs, p->e_private, c,
486 &bv, &a_metaocs[1], NULL );
487 }
488
489 return LDAP_SUCCESS;
490 }
491
492 static int
asyncmeta_back_new_target(a_metatarget_t ** mtp)493 asyncmeta_back_new_target(
494 a_metatarget_t **mtp )
495 {
496 a_metatarget_t *mt;
497
498 *mtp = NULL;
499
500 mt = ch_calloc( sizeof( a_metatarget_t ), 1 );
501
502 ldap_pvt_thread_mutex_init( &mt->mt_uri_mutex );
503
504 mt->mt_idassert_mode = LDAP_BACK_IDASSERT_LEGACY;
505 mt->mt_idassert_authmethod = LDAP_AUTH_NONE;
506 mt->mt_idassert_tls = SB_TLS_DEFAULT;
507 /* by default, use proxyAuthz control on each operation */
508 mt->mt_idassert_flags = LDAP_BACK_AUTH_PRESCRIPTIVE;
509
510 *mtp = mt;
511
512 return 0;
513 }
514
515 /* suffixmassage config */
516 static int
asyncmeta_suffixm_config(ConfigArgs * c,int argc,char ** argv,a_metatarget_t * mt)517 asyncmeta_suffixm_config(
518 ConfigArgs *c,
519 int argc,
520 char **argv,
521 a_metatarget_t *mt
522 )
523 {
524 BackendDB *tmp_bd;
525 struct berval dn, nvnc, pvnc, nrnc, prnc;
526 int j;
527
528 /*
529 * syntax:
530 *
531 * suffixmassage <local suffix> <remote suffix>
532 *
533 * the <local suffix> field must be defined as a valid suffix
534 * (or suffixAlias?) for the current database;
535 * the <remote suffix> shouldn't have already been
536 * defined as a valid suffix or suffixAlias for the
537 * current server
538 */
539
540 ber_str2bv( argv[ 1 ], 0, 0, &dn );
541 if ( dnPrettyNormal( NULL, &dn, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
542 snprintf( c->cr_msg, sizeof( c->cr_msg ),
543 "suffix \"%s\" is invalid",
544 argv[1] );
545 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
546 return 1;
547 }
548
549 for ( j = 0; !BER_BVISNULL( &c->be->be_nsuffix[ j ] ); j++ ) {
550 if ( dnIsSuffix( &nvnc, &c->be->be_nsuffix[ 0 ] ) ) {
551 break;
552 }
553 }
554
555 if ( BER_BVISNULL( &c->be->be_nsuffix[ j ] ) ) {
556 snprintf( c->cr_msg, sizeof( c->cr_msg ),
557 "suffix \"%s\" must be within the database naming context",
558 argv[1] );
559 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
560 free( pvnc.bv_val );
561 free( nvnc.bv_val );
562 return 1;
563 }
564
565 ber_str2bv( argv[ 2 ], 0, 0, &dn );
566 if ( dnPrettyNormal( NULL, &dn, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
567 snprintf( c->cr_msg, sizeof( c->cr_msg ),
568 "massaged suffix \"%s\" is invalid",
569 argv[2] );
570 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
571 free( pvnc.bv_val );
572 free( nvnc.bv_val );
573 return 1;
574 }
575
576 tmp_bd = select_backend( &nrnc, 0 );
577 if ( tmp_bd != NULL && tmp_bd->be_private == c->be->be_private ) {
578 Debug( LDAP_DEBUG_ANY,
579 "%s: warning: <massaged suffix> \"%s\" resolves to this database, in "
580 "\"suffixMassage <suffix> <massaged suffix>\"\n",
581 c->log, prnc.bv_val );
582 }
583
584 mt->mt_lsuffixm = pvnc;
585 mt->mt_rsuffixm = prnc;
586
587 free( nvnc.bv_val );
588 free( nrnc.bv_val );
589
590 return 0;
591 }
592
593 int
asyncmeta_subtree_free(a_metasubtree_t * ms)594 asyncmeta_subtree_free( a_metasubtree_t *ms )
595 {
596 switch ( ms->ms_type ) {
597 case META_ST_SUBTREE:
598 case META_ST_SUBORDINATE:
599 ber_memfree( ms->ms_dn.bv_val );
600 break;
601
602 case META_ST_REGEX:
603 regfree( &ms->ms_regex );
604 ber_memfree( ms->ms_regex_pattern.bv_val );
605 break;
606
607 default:
608 return -1;
609 }
610
611 ch_free( ms );
612 return 0;
613 }
614
615 int
asyncmeta_subtree_destroy(a_metasubtree_t * ms)616 asyncmeta_subtree_destroy( a_metasubtree_t *ms )
617 {
618 if ( ms->ms_next ) {
619 asyncmeta_subtree_destroy( ms->ms_next );
620 }
621
622 return asyncmeta_subtree_free( ms );
623 }
624
625 static void
asyncmeta_filter_free(metafilter_t * mf)626 asyncmeta_filter_free( metafilter_t *mf )
627 {
628 regfree( &mf->mf_regex );
629 ber_memfree( mf->mf_regex_pattern.bv_val );
630 ch_free( mf );
631 }
632
633 void
asyncmeta_filter_destroy(metafilter_t * mf)634 asyncmeta_filter_destroy( metafilter_t *mf )
635 {
636 if ( mf->mf_next )
637 asyncmeta_filter_destroy( mf->mf_next );
638 asyncmeta_filter_free( mf );
639 }
640
641 static struct berval st_styles[] = {
642 BER_BVC("subtree"),
643 BER_BVC("children"),
644 BER_BVC("regex")
645 };
646
647 static int
asyncmeta_subtree_unparse(ConfigArgs * c,a_metatarget_t * mt)648 asyncmeta_subtree_unparse(
649 ConfigArgs *c,
650 a_metatarget_t *mt )
651 {
652 a_metasubtree_t *ms;
653 struct berval bv, *style;
654
655 if ( !mt->mt_subtree )
656 return 1;
657
658 /* can only be one of exclude or include */
659 if (( c->type == LDAP_BACK_CFG_SUBTREE_EX ) ^ mt->mt_subtree_exclude )
660 return 1;
661
662 bv.bv_val = c->cr_msg;
663 for ( ms=mt->mt_subtree; ms; ms=ms->ms_next ) {
664 if (ms->ms_type == META_ST_SUBTREE)
665 style = &st_styles[0];
666 else if ( ms->ms_type == META_ST_SUBORDINATE )
667 style = &st_styles[1];
668 else if ( ms->ms_type == META_ST_REGEX )
669 style = &st_styles[2];
670 else {
671 assert(0);
672 continue;
673 }
674 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg),
675 "dn.%s:%s", style->bv_val, ms->ms_dn.bv_val );
676 value_add_one( &c->rvalue_vals, &bv );
677 }
678 return 0;
679 }
680
681 static int
asyncmeta_subtree_config(a_metatarget_t * mt,ConfigArgs * c)682 asyncmeta_subtree_config(
683 a_metatarget_t *mt,
684 ConfigArgs *c )
685 {
686 meta_st_t type = META_ST_SUBTREE;
687 char *pattern;
688 struct berval ndn = BER_BVNULL;
689 a_metasubtree_t *ms = NULL;
690
691 if ( c->type == LDAP_BACK_CFG_SUBTREE_EX ) {
692 if ( mt->mt_subtree && !mt->mt_subtree_exclude ) {
693 snprintf( c->cr_msg, sizeof(c->cr_msg),
694 "\"subtree-exclude\" incompatible with previous \"subtree-include\" directives" );
695 return 1;
696 }
697
698 mt->mt_subtree_exclude = 1;
699
700 } else {
701 if ( mt->mt_subtree && mt->mt_subtree_exclude ) {
702 snprintf( c->cr_msg, sizeof(c->cr_msg),
703 "\"subtree-include\" incompatible with previous \"subtree-exclude\" directives" );
704 return 1;
705 }
706 }
707
708 pattern = c->argv[1];
709 if ( strncasecmp( pattern, "dn", STRLENOF( "dn" ) ) == 0 ) {
710 char *style;
711
712 pattern = &pattern[STRLENOF( "dn")];
713
714 if ( pattern[0] == '.' ) {
715 style = &pattern[1];
716
717 if ( strncasecmp( style, "subtree", STRLENOF( "subtree" ) ) == 0 ) {
718 type = META_ST_SUBTREE;
719 pattern = &style[STRLENOF( "subtree" )];
720
721 } else if ( strncasecmp( style, "children", STRLENOF( "children" ) ) == 0 ) {
722 type = META_ST_SUBORDINATE;
723 pattern = &style[STRLENOF( "children" )];
724
725 } else if ( strncasecmp( style, "sub", STRLENOF( "sub" ) ) == 0 ) {
726 type = META_ST_SUBTREE;
727 pattern = &style[STRLENOF( "sub" )];
728
729 } else if ( strncasecmp( style, "regex", STRLENOF( "regex" ) ) == 0 ) {
730 type = META_ST_REGEX;
731 pattern = &style[STRLENOF( "regex" )];
732
733 } else {
734 snprintf( c->cr_msg, sizeof(c->cr_msg), "unknown style in \"dn.<style>\"" );
735 return 1;
736 }
737 }
738
739 if ( pattern[0] != ':' ) {
740 snprintf( c->cr_msg, sizeof(c->cr_msg), "missing colon after \"dn.<style>\"" );
741 return 1;
742 }
743 pattern++;
744 }
745
746 switch ( type ) {
747 case META_ST_SUBTREE:
748 case META_ST_SUBORDINATE: {
749 struct berval dn;
750
751 ber_str2bv( pattern, 0, 0, &dn );
752 if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL )
753 != LDAP_SUCCESS )
754 {
755 snprintf( c->cr_msg, sizeof(c->cr_msg), "DN=\"%s\" is invalid", pattern );
756 return 1;
757 }
758
759 if ( !dnIsSuffix( &ndn, &mt->mt_nsuffix ) ) {
760 snprintf( c->cr_msg, sizeof(c->cr_msg),
761 "DN=\"%s\" is not a subtree of target \"%s\"",
762 pattern, mt->mt_nsuffix.bv_val );
763 ber_memfree( ndn.bv_val );
764 return( 1 );
765 }
766 } break;
767
768 default:
769 /* silence warnings */
770 break;
771 }
772
773 ms = ch_calloc( sizeof( a_metasubtree_t ), 1 );
774 ms->ms_type = type;
775
776 switch ( ms->ms_type ) {
777 case META_ST_SUBTREE:
778 case META_ST_SUBORDINATE:
779 ms->ms_dn = ndn;
780 break;
781
782 case META_ST_REGEX: {
783 int rc;
784
785 rc = regcomp( &ms->ms_regex, pattern, REG_EXTENDED|REG_ICASE );
786 if ( rc != 0 ) {
787 char regerr[ SLAP_TEXT_BUFLEN ];
788
789 regerror( rc, &ms->ms_regex, regerr, sizeof(regerr) );
790
791 snprintf( c->cr_msg, sizeof( c->cr_msg ),
792 "regular expression \"%s\" bad because of %s",
793 pattern, regerr );
794 ch_free( ms );
795 return 1;
796 }
797 ber_str2bv( pattern, 0, 1, &ms->ms_regex_pattern );
798 } break;
799 }
800
801 if ( mt->mt_subtree == NULL ) {
802 mt->mt_subtree = ms;
803
804 } else {
805 a_metasubtree_t **msp;
806
807 for ( msp = &mt->mt_subtree; *msp; ) {
808 switch ( ms->ms_type ) {
809 case META_ST_SUBTREE:
810 switch ( (*msp)->ms_type ) {
811 case META_ST_SUBTREE:
812 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
813 a_metasubtree_t *tmp = *msp;
814 Debug( LDAP_DEBUG_CONFIG,
815 "%s: previous rule \"dn.subtree:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n",
816 c->log, pattern, (*msp)->ms_dn.bv_val );
817 *msp = (*msp)->ms_next;
818 tmp->ms_next = NULL;
819 asyncmeta_subtree_destroy( tmp );
820 continue;
821
822 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) ) {
823 Debug( LDAP_DEBUG_CONFIG,
824 "%s: previous rule \"dn.subtree:%s\" contains rule \"dn.subtree:%s\" (ignored)\n",
825 c->log, (*msp)->ms_dn.bv_val, pattern );
826 asyncmeta_subtree_destroy( ms );
827 ms = NULL;
828 return( 0 );
829 }
830 break;
831
832 case META_ST_SUBORDINATE:
833 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
834 a_metasubtree_t *tmp = *msp;
835 Debug( LDAP_DEBUG_CONFIG,
836 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n",
837 c->log, pattern, (*msp)->ms_dn.bv_val );
838 *msp = (*msp)->ms_next;
839 tmp->ms_next = NULL;
840 asyncmeta_subtree_destroy( tmp );
841 continue;
842
843 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) && ms->ms_dn.bv_len > (*msp)->ms_dn.bv_len ) {
844 Debug( LDAP_DEBUG_CONFIG,
845 "%s: previous rule \"dn.children:%s\" contains rule \"dn.subtree:%s\" (ignored)\n",
846 c->log, (*msp)->ms_dn.bv_val, pattern );
847 asyncmeta_subtree_destroy( ms );
848 ms = NULL;
849 return( 0 );
850 }
851 break;
852
853 case META_ST_REGEX:
854 if ( regexec( &(*msp)->ms_regex, ms->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) {
855 Debug( LDAP_DEBUG_CONFIG,
856 "%s: previous rule \"dn.regex:%s\" may contain rule \"dn.subtree:%s\"\n",
857 c->log, (*msp)->ms_regex_pattern.bv_val, ms->ms_dn.bv_val );
858 }
859 break;
860 }
861 break;
862
863 case META_ST_SUBORDINATE:
864 switch ( (*msp)->ms_type ) {
865 case META_ST_SUBTREE:
866 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
867 a_metasubtree_t *tmp = *msp;
868 Debug( LDAP_DEBUG_CONFIG,
869 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n",
870 c->log, pattern, (*msp)->ms_dn.bv_val );
871 *msp = (*msp)->ms_next;
872 tmp->ms_next = NULL;
873 asyncmeta_subtree_destroy( tmp );
874 continue;
875
876 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) && ms->ms_dn.bv_len > (*msp)->ms_dn.bv_len ) {
877 Debug( LDAP_DEBUG_CONFIG,
878 "%s: previous rule \"dn.children:%s\" contains rule \"dn.subtree:%s\" (ignored)\n",
879 c->log, (*msp)->ms_dn.bv_val, pattern );
880 asyncmeta_subtree_destroy( ms );
881 ms = NULL;
882 return( 0 );
883 }
884 break;
885
886 case META_ST_SUBORDINATE:
887 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
888 a_metasubtree_t *tmp = *msp;
889 Debug( LDAP_DEBUG_CONFIG,
890 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.children:%s\" (replaced)\n",
891 c->log, pattern, (*msp)->ms_dn.bv_val );
892 *msp = (*msp)->ms_next;
893 tmp->ms_next = NULL;
894 asyncmeta_subtree_destroy( tmp );
895 continue;
896
897 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) ) {
898 Debug( LDAP_DEBUG_CONFIG,
899 "%s: previous rule \"dn.children:%s\" contains rule \"dn.children:%s\" (ignored)\n",
900 c->log, (*msp)->ms_dn.bv_val, pattern );
901 asyncmeta_subtree_destroy( ms );
902 ms = NULL;
903 return( 0 );
904 }
905 break;
906
907 case META_ST_REGEX:
908 if ( regexec( &(*msp)->ms_regex, ms->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) {
909 Debug( LDAP_DEBUG_CONFIG,
910 "%s: previous rule \"dn.regex:%s\" may contain rule \"dn.subtree:%s\"\n",
911 c->log, (*msp)->ms_regex_pattern.bv_val, ms->ms_dn.bv_val );
912 }
913 break;
914 }
915 break;
916
917 case META_ST_REGEX:
918 switch ( (*msp)->ms_type ) {
919 case META_ST_SUBTREE:
920 case META_ST_SUBORDINATE:
921 if ( regexec( &ms->ms_regex, (*msp)->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) {
922 Debug( LDAP_DEBUG_CONFIG,
923 "%s: previous rule \"dn.subtree:%s\" may be contained in rule \"dn.regex:%s\"\n",
924 c->log, (*msp)->ms_dn.bv_val, ms->ms_regex_pattern.bv_val );
925 }
926 break;
927
928 case META_ST_REGEX:
929 /* no check possible */
930 break;
931 }
932 break;
933 }
934
935 msp = &(*msp)->ms_next;
936 }
937
938 *msp = ms;
939 }
940
941 return 0;
942 }
943
944 static slap_verbmasks idassert_mode[] = {
945 { BER_BVC("self"), LDAP_BACK_IDASSERT_SELF },
946 { BER_BVC("anonymous"), LDAP_BACK_IDASSERT_ANONYMOUS },
947 { BER_BVC("none"), LDAP_BACK_IDASSERT_NOASSERT },
948 { BER_BVC("legacy"), LDAP_BACK_IDASSERT_LEGACY },
949 { BER_BVNULL, 0 }
950 };
951
952 static slap_verbmasks tls_mode[] = {
953 { BER_BVC( "propagate" ), LDAP_BACK_F_TLS_PROPAGATE_MASK },
954 { BER_BVC( "try-propagate" ), LDAP_BACK_F_PROPAGATE_TLS },
955 { BER_BVC( "start" ), LDAP_BACK_F_TLS_USE_MASK },
956 { BER_BVC( "try-start" ), LDAP_BACK_F_USE_TLS },
957 { BER_BVC( "ldaps" ), LDAP_BACK_F_TLS_LDAPS },
958 { BER_BVC( "none" ), LDAP_BACK_F_NONE },
959 { BER_BVNULL, 0 }
960 };
961
962 static slap_verbmasks t_f_mode[] = {
963 { BER_BVC( "yes" ), LDAP_BACK_F_T_F },
964 { BER_BVC( "discover" ), LDAP_BACK_F_T_F_DISCOVER },
965 { BER_BVC( "no" ), LDAP_BACK_F_NONE },
966 { BER_BVNULL, 0 }
967 };
968
969 static slap_verbmasks cancel_mode[] = {
970 { BER_BVC( "ignore" ), LDAP_BACK_F_CANCEL_IGNORE },
971 { BER_BVC( "exop" ), LDAP_BACK_F_CANCEL_EXOP },
972 { BER_BVC( "exop-discover" ), LDAP_BACK_F_CANCEL_EXOP_DISCOVER },
973 { BER_BVC( "abandon" ), LDAP_BACK_F_CANCEL_ABANDON },
974 { BER_BVNULL, 0 }
975 };
976
977 static slap_verbmasks onerr_mode[] = {
978 { BER_BVC( "stop" ), META_BACK_F_ONERR_STOP },
979 { BER_BVC( "report" ), META_BACK_F_ONERR_REPORT },
980 { BER_BVC( "continue" ), LDAP_BACK_F_NONE },
981 { BER_BVNULL, 0 }
982 };
983
984 /* see enum in slap.h */
985 static slap_cf_aux_table timeout_table[] = {
986 { BER_BVC("bind="), SLAP_OP_BIND * sizeof( time_t ), 'u', 0, NULL },
987 /* unbind makes no sense */
988 { BER_BVC("add="), SLAP_OP_ADD * sizeof( time_t ), 'u', 0, NULL },
989 { BER_BVC("delete="), SLAP_OP_DELETE * sizeof( time_t ), 'u', 0, NULL },
990 { BER_BVC("modrdn="), SLAP_OP_MODRDN * sizeof( time_t ), 'u', 0, NULL },
991 { BER_BVC("modify="), SLAP_OP_MODIFY * sizeof( time_t ), 'u', 0, NULL },
992 { BER_BVC("compare="), SLAP_OP_COMPARE * sizeof( time_t ), 'u', 0, NULL },
993 { BER_BVC("search="), SLAP_OP_SEARCH * sizeof( time_t ), 'u', 0, NULL },
994 /* abandon makes little sense */
995 #if 0 /* not implemented yet */
996 { BER_BVC("extended="), SLAP_OP_EXTENDED * sizeof( time_t ), 'u', 0, NULL },
997 #endif
998 { BER_BVNULL, 0, 0, 0, NULL }
999 };
1000
1001 static int
asyncmeta_cf_cleanup(ConfigArgs * c)1002 asyncmeta_cf_cleanup( ConfigArgs *c )
1003 {
1004 a_metainfo_t *mi = ( a_metainfo_t * )c->be->be_private;
1005 a_metatarget_t *mt = c->ca_private;
1006
1007 return asyncmeta_target_finish( mi, mt, c->log, c->cr_msg, sizeof( c->cr_msg ));
1008 }
1009
1010 static int
asyncmeta_back_cf_gen(ConfigArgs * c)1011 asyncmeta_back_cf_gen( ConfigArgs *c )
1012 {
1013 a_metainfo_t *mi = ( a_metainfo_t * )c->be->be_private;
1014 a_metatarget_t *mt = NULL;
1015 a_metacommon_t *mc = NULL;
1016
1017 int i, rc = 0;
1018
1019 assert( mi != NULL );
1020
1021 if ( c->op == SLAP_CONFIG_EMIT || c->op == LDAP_MOD_DELETE ) {
1022 if ( !mi )
1023 return 1;
1024
1025 if ( c->table == Cft_Database ) {
1026 mt = NULL;
1027 mc = &mi->mi_mc;
1028 } else {
1029 mt = c->ca_private;
1030 mc = &mt->mt_mc;
1031 }
1032 }
1033
1034 if ( c->op == SLAP_CONFIG_EMIT ) {
1035 struct berval bv = BER_BVNULL;
1036
1037 switch( c->type ) {
1038 /* Base attrs */
1039
1040 case LDAP_BACK_CFG_DNCACHE_TTL:
1041 if ( mi->mi_cache.ttl == META_DNCACHE_DISABLED ) {
1042 return 1;
1043 } else if ( mi->mi_cache.ttl == META_DNCACHE_FOREVER ) {
1044 BER_BVSTR( &bv, "forever" );
1045 } else {
1046 char buf[ SLAP_TEXT_BUFLEN ];
1047
1048 lutil_unparse_time( buf, sizeof( buf ), mi->mi_cache.ttl );
1049 ber_str2bv( buf, 0, 0, &bv );
1050 }
1051 value_add_one( &c->rvalue_vals, &bv );
1052 break;
1053
1054 case LDAP_BACK_CFG_IDLE_TIMEOUT:
1055 if ( mi->mi_idle_timeout == 0 ) {
1056 return 1;
1057 } else {
1058 char buf[ SLAP_TEXT_BUFLEN ];
1059
1060 lutil_unparse_time( buf, sizeof( buf ), mi->mi_idle_timeout );
1061 ber_str2bv( buf, 0, 0, &bv );
1062 value_add_one( &c->rvalue_vals, &bv );
1063 }
1064 break;
1065
1066 case LDAP_BACK_CFG_ONERR:
1067 enum_to_verb( onerr_mode, mi->mi_flags & META_BACK_F_ONERR_MASK, &bv );
1068 if ( BER_BVISNULL( &bv )) {
1069 rc = 1;
1070 } else {
1071 value_add_one( &c->rvalue_vals, &bv );
1072 }
1073 break;
1074
1075 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER:
1076 c->value_int = META_BACK_DEFER_ROOTDN_BIND( mi );
1077 break;
1078
1079 case LDAP_BACK_CFG_CONNPOOLMAX:
1080 c->value_int = mi->mi_conn_priv_max;
1081 break;
1082
1083 /* common attrs */
1084 case LDAP_BACK_CFG_BIND_TIMEOUT:
1085 if ( mc->mc_bind_timeout.tv_sec == 0 &&
1086 mc->mc_bind_timeout.tv_usec == 0 ) {
1087 return 1;
1088 } else {
1089 c->value_ulong = mc->mc_bind_timeout.tv_sec * 1000000UL +
1090 mc->mc_bind_timeout.tv_usec;
1091 }
1092 break;
1093
1094 case LDAP_BACK_CFG_CANCEL: {
1095 slap_mask_t mask = LDAP_BACK_F_CANCEL_MASK2;
1096
1097 if ( mt && META_BACK_TGT_CANCEL_DISCOVER( mt ) ) {
1098 mask &= ~LDAP_BACK_F_CANCEL_EXOP;
1099 }
1100 enum_to_verb( cancel_mode, (mc->mc_flags & mask), &bv );
1101 if ( BER_BVISNULL( &bv ) ) {
1102 /* there's something wrong... */
1103 assert( 0 );
1104 rc = 1;
1105
1106 } else {
1107 value_add_one( &c->rvalue_vals, &bv );
1108 }
1109 } break;
1110
1111 case LDAP_BACK_CFG_CHASE:
1112 c->value_int = META_BACK_CMN_CHASE_REFERRALS(mc);
1113 break;
1114
1115 #ifdef SLAPD_META_CLIENT_PR
1116 case LDAP_BACK_CFG_CLIENT_PR:
1117 if ( mc->mc_ps == META_CLIENT_PR_DISABLE ) {
1118 return 1;
1119 } else if ( mc->mc_ps == META_CLIENT_PR_ACCEPT_UNSOLICITED ) {
1120 BER_BVSTR( &bv, "accept-unsolicited" );
1121 } else {
1122 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d", mc->mc_ps );
1123 bv.bv_val = c->cr_msg;
1124 }
1125 value_add_one( &c->rvalue_vals, &bv );
1126 break;
1127 #endif /* SLAPD_META_CLIENT_PR */
1128
1129 case LDAP_BACK_CFG_DEFAULT_T:
1130 if ( mt || mi->mi_defaulttarget == META_DEFAULT_TARGET_NONE )
1131 return 1;
1132 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d", mi->mi_defaulttarget );
1133 bv.bv_val = c->cr_msg;
1134 value_add_one( &c->rvalue_vals, &bv );
1135 break;
1136
1137 case LDAP_BACK_CFG_NETWORK_TIMEOUT:
1138 if ( mc->mc_network_timeout == 0 ) {
1139 return 1;
1140 }
1141 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%ld",
1142 mc->mc_network_timeout );
1143 bv.bv_val = c->cr_msg;
1144 value_add_one( &c->rvalue_vals, &bv );
1145 break;
1146
1147 case LDAP_BACK_CFG_NOREFS:
1148 c->value_int = META_BACK_CMN_NOREFS(mc);
1149 break;
1150
1151 case LDAP_BACK_CFG_NOUNDEFFILTER:
1152 c->value_int = META_BACK_CMN_NOUNDEFFILTER(mc);
1153 break;
1154
1155 case LDAP_BACK_CFG_NRETRIES:
1156 if ( mc->mc_nretries == META_RETRY_FOREVER ) {
1157 BER_BVSTR( &bv, "forever" );
1158 } else if ( mc->mc_nretries == META_RETRY_NEVER ) {
1159 BER_BVSTR( &bv, "never" );
1160 } else {
1161 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d",
1162 mc->mc_nretries );
1163 bv.bv_val = c->cr_msg;
1164 }
1165 value_add_one( &c->rvalue_vals, &bv );
1166 break;
1167
1168 case LDAP_BACK_CFG_QUARANTINE:
1169 if ( !META_BACK_CMN_QUARANTINE( mc )) {
1170 rc = 1;
1171 break;
1172 }
1173 rc = mi->mi_ldap_extra->retry_info_unparse( &mc->mc_quarantine, &bv );
1174 if ( rc == 0 ) {
1175 ber_bvarray_add( &c->rvalue_vals, &bv );
1176 }
1177 break;
1178
1179 case LDAP_BACK_CFG_REBIND:
1180 c->value_int = META_BACK_CMN_SAVECRED(mc);
1181 break;
1182
1183 case LDAP_BACK_CFG_TIMEOUT:
1184 for ( i = 0; i < SLAP_OP_LAST; i++ ) {
1185 if ( mc->mc_timeout[ i ] != META_BACK_CFG_DEFAULT_OPS_TIMEOUT ) {
1186 break;
1187 }
1188 }
1189
1190 if ( i == SLAP_OP_LAST ) {
1191 return 1;
1192 }
1193
1194 BER_BVZERO( &bv );
1195 slap_cf_aux_table_unparse( mc->mc_timeout, &bv, timeout_table );
1196
1197 if ( BER_BVISNULL( &bv ) ) {
1198 return 1;
1199 }
1200
1201 for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ )
1202 /* count spaces */ ;
1203
1204 if ( i ) {
1205 bv.bv_len -= i;
1206 AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ],
1207 bv.bv_len + 1 );
1208 }
1209
1210 ber_bvarray_add( &c->rvalue_vals, &bv );
1211 break;
1212
1213 case LDAP_BACK_CFG_VERSION:
1214 if ( mc->mc_version == 0 )
1215 return 1;
1216 c->value_int = mc->mc_version;
1217 break;
1218
1219 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
1220 case LDAP_BACK_CFG_ST_REQUEST:
1221 c->value_int = META_BACK_CMN_ST_REQUEST( mc );
1222 break;
1223 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
1224
1225 case LDAP_BACK_CFG_T_F:
1226 enum_to_verb( t_f_mode, (mc->mc_flags & LDAP_BACK_F_T_F_MASK2), &bv );
1227 if ( BER_BVISNULL( &bv ) ) {
1228 /* there's something wrong... */
1229 assert( 0 );
1230 rc = 1;
1231
1232 } else {
1233 value_add_one( &c->rvalue_vals, &bv );
1234 }
1235 break;
1236
1237 case LDAP_BACK_CFG_TLS: {
1238 struct berval bc = BER_BVNULL, bv2;
1239
1240 if (( mc->mc_flags & LDAP_BACK_F_TLS_MASK ) == LDAP_BACK_F_NONE ) {
1241 rc = 1;
1242 break;
1243 }
1244 enum_to_verb( tls_mode, ( mc->mc_flags & LDAP_BACK_F_TLS_MASK ), &bv );
1245 assert( !BER_BVISNULL( &bv ) );
1246
1247 if ( mt ) {
1248 bindconf_tls_unparse( &mt->mt_tls, &bc );
1249 }
1250
1251 if ( !BER_BVISEMPTY( &bc )) {
1252 bv2.bv_len = bv.bv_len + bc.bv_len + 1;
1253 bv2.bv_val = ch_malloc( bv2.bv_len + 1 );
1254 strcpy( bv2.bv_val, bv.bv_val );
1255 bv2.bv_val[bv.bv_len] = ' ';
1256 strcpy( &bv2.bv_val[bv.bv_len + 1], bc.bv_val );
1257 ber_memfree( bc.bv_val );
1258 ber_bvarray_add( &c->rvalue_vals, &bv2 );
1259 } else {
1260 value_add_one( &c->rvalue_vals, &bv );
1261 }
1262 } break;
1263
1264 /* target attrs */
1265 case LDAP_BACK_CFG_URI: {
1266 char *p2, *p1 = strchr( mt->mt_uri, ' ' );
1267 bv.bv_len = strlen( mt->mt_uri ) + 3 + mt->mt_psuffix.bv_len;
1268 bv.bv_val = ch_malloc( bv.bv_len + 1 );
1269 p2 = bv.bv_val;
1270 *p2++ = '"';
1271 if ( p1 ) {
1272 p2 = lutil_strncopy( p2, mt->mt_uri, p1 - mt->mt_uri );
1273 } else {
1274 p2 = lutil_strcopy( p2, mt->mt_uri );
1275 }
1276 *p2++ = '/';
1277 p2 = lutil_strcopy( p2, mt->mt_psuffix.bv_val );
1278 *p2++ = '"';
1279 if ( p1 ) {
1280 strcpy( p2, p1 );
1281 }
1282 ber_bvarray_add( &c->rvalue_vals, &bv );
1283 } break;
1284
1285 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
1286 BerVarray *bvp;
1287 int i;
1288 struct berval bv = BER_BVNULL;
1289 char buf[SLAP_TEXT_BUFLEN];
1290
1291 bvp = &mt->mt_idassert_authz;
1292 if ( *bvp == NULL ) {
1293 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL )
1294 {
1295 BER_BVSTR( &bv, "*" );
1296 value_add_one( &c->rvalue_vals, &bv );
1297
1298 } else {
1299 rc = 1;
1300 }
1301 break;
1302 }
1303
1304 for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ ) {
1305 char *ptr;
1306 int len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i );
1307 bv.bv_len = ((*bvp)[ i ]).bv_len + len;
1308 bv.bv_val = ber_memrealloc( bv.bv_val, bv.bv_len + 1 );
1309 ptr = bv.bv_val;
1310 ptr = lutil_strcopy( ptr, buf );
1311 ptr = lutil_strncopy( ptr, ((*bvp)[ i ]).bv_val, ((*bvp)[ i ]).bv_len );
1312 value_add_one( &c->rvalue_vals, &bv );
1313 }
1314 if ( bv.bv_val ) {
1315 ber_memfree( bv.bv_val );
1316 }
1317 break;
1318 }
1319
1320 case LDAP_BACK_CFG_IDASSERT_BIND: {
1321 int i;
1322 struct berval bc = BER_BVNULL;
1323 char *ptr;
1324
1325 if ( mt->mt_idassert_authmethod == LDAP_AUTH_NONE ) {
1326 return 1;
1327 } else {
1328 ber_len_t len;
1329
1330 switch ( mt->mt_idassert_mode ) {
1331 case LDAP_BACK_IDASSERT_OTHERID:
1332 case LDAP_BACK_IDASSERT_OTHERDN:
1333 break;
1334
1335 default: {
1336 struct berval mode = BER_BVNULL;
1337
1338 enum_to_verb( idassert_mode, mt->mt_idassert_mode, &mode );
1339 if ( BER_BVISNULL( &mode ) ) {
1340 /* there's something wrong... */
1341 assert( 0 );
1342 rc = 1;
1343
1344 } else {
1345 bv.bv_len = STRLENOF( "mode=" ) + mode.bv_len;
1346 bv.bv_val = ch_malloc( bv.bv_len + 1 );
1347
1348 ptr = lutil_strcopy( bv.bv_val, "mode=" );
1349 ptr = lutil_strcopy( ptr, mode.bv_val );
1350 }
1351 break;
1352 }
1353 }
1354
1355 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) {
1356 len = bv.bv_len + STRLENOF( "authz=native" );
1357
1358 if ( !BER_BVISEMPTY( &bv ) ) {
1359 len += STRLENOF( " " );
1360 }
1361
1362 bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
1363
1364 ptr = &bv.bv_val[ bv.bv_len ];
1365
1366 if ( !BER_BVISEMPTY( &bv ) ) {
1367 ptr = lutil_strcopy( ptr, " " );
1368 }
1369
1370 (void)lutil_strcopy( ptr, "authz=native" );
1371 }
1372
1373 len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override,obsolete-encoding-workaround,proxy-authz-non-critical,dn-authzid" );
1374 /* flags */
1375 if ( !BER_BVISEMPTY( &bv ) ) {
1376 len += STRLENOF( " " );
1377 }
1378
1379 bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
1380
1381 ptr = &bv.bv_val[ bv.bv_len ];
1382
1383 if ( !BER_BVISEMPTY( &bv ) ) {
1384 ptr = lutil_strcopy( ptr, " " );
1385 }
1386
1387 ptr = lutil_strcopy( ptr, "flags=" );
1388
1389 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
1390 ptr = lutil_strcopy( ptr, "prescriptive" );
1391 } else {
1392 ptr = lutil_strcopy( ptr, "non-prescriptive" );
1393 }
1394
1395 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
1396 ptr = lutil_strcopy( ptr, ",override" );
1397 }
1398
1399 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
1400 ptr = lutil_strcopy( ptr, ",obsolete-proxy-authz" );
1401
1402 } else if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
1403 ptr = lutil_strcopy( ptr, ",obsolete-encoding-workaround" );
1404 }
1405
1406 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL ) {
1407 ptr = lutil_strcopy( ptr, ",proxy-authz-critical" );
1408
1409 } else {
1410 ptr = lutil_strcopy( ptr, ",proxy-authz-non-critical" );
1411 }
1412
1413 #ifdef SLAP_AUTH_DN
1414 switch ( mt->mt_idassert_flags & LDAP_BACK_AUTH_DN_MASK ) {
1415 case LDAP_BACK_AUTH_DN_AUTHZID:
1416 ptr = lutil_strcopy( ptr, ",dn-authzid" );
1417 break;
1418
1419 case LDAP_BACK_AUTH_DN_WHOAMI:
1420 ptr = lutil_strcopy( ptr, ",dn-whoami" );
1421 break;
1422
1423 default:
1424 #if 0 /* implicit */
1425 ptr = lutil_strcopy( ptr, ",dn-none" );
1426 #endif
1427 break;
1428 }
1429 #endif
1430
1431 bv.bv_len = ( ptr - bv.bv_val );
1432 /* end-of-flags */
1433 }
1434
1435 bindconf_unparse( &mt->mt_idassert.si_bc, &bc );
1436
1437 if ( !BER_BVISNULL( &bv ) ) {
1438 ber_len_t len = bv.bv_len + bc.bv_len;
1439
1440 bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
1441
1442 assert( bc.bv_val[ 0 ] == ' ' );
1443
1444 ptr = lutil_strcopy( &bv.bv_val[ bv.bv_len ], bc.bv_val );
1445 free( bc.bv_val );
1446 bv.bv_len = ptr - bv.bv_val;
1447
1448 } else {
1449 for ( i = 0; isspace( (unsigned char) bc.bv_val[ i ] ); i++ )
1450 /* count spaces */ ;
1451
1452 if ( i ) {
1453 bc.bv_len -= i;
1454 AC_MEMCPY( bc.bv_val, &bc.bv_val[ i ], bc.bv_len + 1 );
1455 }
1456
1457 bv = bc;
1458 }
1459
1460 ber_bvarray_add( &c->rvalue_vals, &bv );
1461
1462 break;
1463 }
1464
1465 case LDAP_BACK_CFG_SUFFIXM:
1466 if ( mt->mt_lsuffixm.bv_val ) {
1467 struct berval bv;
1468 char *ptr;
1469 bv.bv_len = mt->mt_lsuffixm.bv_len + 2 + 1 + mt->mt_rsuffixm.bv_len + 2;
1470 bv.bv_val = ch_malloc( bv.bv_len + 1 );
1471 ptr = bv.bv_val;
1472 *ptr++ = '"';
1473 ptr = lutil_strcopy(ptr, mt->mt_lsuffixm.bv_val);
1474 ptr = lutil_strcopy(ptr, "\" \"");
1475 ptr = lutil_strcopy(ptr, mt->mt_rsuffixm.bv_val);
1476 *ptr++ = '"';
1477 *ptr = '\0';
1478 ber_bvarray_add( &c->rvalue_vals, &bv );
1479 rc = 0;
1480 } else
1481 rc = 1;
1482 break;
1483
1484 case LDAP_BACK_CFG_SUBTREE_EX:
1485 case LDAP_BACK_CFG_SUBTREE_IN:
1486 rc = asyncmeta_subtree_unparse( c, mt );
1487 break;
1488
1489 case LDAP_BACK_CFG_FILTER:
1490 if ( mt->mt_filter == NULL ) {
1491 rc = 1;
1492 } else {
1493 metafilter_t *mf;
1494 for ( mf = mt->mt_filter; mf; mf = mf->mf_next )
1495 value_add_one( &c->rvalue_vals, &mf->mf_regex_pattern );
1496 }
1497 break;
1498 case LDAP_BACK_CFG_MAX_PENDING_OPS:
1499 c->value_int = mi->mi_max_pending_ops;
1500 break;
1501
1502 case LDAP_BACK_CFG_MAX_TARGET_CONNS:
1503 c->value_int = mi->mi_max_target_conns;
1504 break;
1505 case LDAP_BACK_CFG_MAX_TIMEOUT_OPS:
1506 c->value_int = mi->mi_max_timeout_ops;
1507 break;
1508
1509 case LDAP_BACK_CFG_KEEPALIVE: {
1510 struct berval bv;
1511 char buf[AC_LINE_MAX];
1512 bv.bv_len = AC_LINE_MAX;
1513 bv.bv_val = &buf[0];
1514 slap_keepalive_parse(&bv, &mt->mt_tls.sb_keepalive, 0, 0, 1);
1515 value_add_one( &c->rvalue_vals, &bv );
1516 break;
1517 }
1518
1519 case LDAP_BACK_CFG_TCP_USER_TIMEOUT:
1520 c->value_uint = mt->mt_tls.sb_tcp_user_timeout;
1521 break;
1522
1523 default:
1524 rc = 1;
1525 }
1526 return rc;
1527 } else if ( c->op == LDAP_MOD_DELETE ) {
1528 switch( c->type ) {
1529 /* Base attrs */
1530 case LDAP_BACK_CFG_DNCACHE_TTL:
1531 mi->mi_cache.ttl = META_DNCACHE_DISABLED;
1532 break;
1533
1534 case LDAP_BACK_CFG_IDLE_TIMEOUT:
1535 mi->mi_idle_timeout = 0;
1536 break;
1537
1538 case LDAP_BACK_CFG_ONERR:
1539 mi->mi_flags &= ~META_BACK_F_ONERR_MASK;
1540 break;
1541
1542 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER:
1543 mi->mi_flags &= ~META_BACK_F_DEFER_ROOTDN_BIND;
1544 break;
1545
1546 case LDAP_BACK_CFG_CONNPOOLMAX:
1547 mi->mi_conn_priv_max = LDAP_BACK_CONN_PRIV_MIN;
1548 break;
1549
1550 /* common attrs */
1551 case LDAP_BACK_CFG_BIND_TIMEOUT:
1552 mc->mc_bind_timeout.tv_sec = 0;
1553 mc->mc_bind_timeout.tv_usec = 0;
1554 break;
1555
1556 case LDAP_BACK_CFG_CANCEL:
1557 mc->mc_flags &= ~LDAP_BACK_F_CANCEL_MASK2;
1558 break;
1559
1560 case LDAP_BACK_CFG_CHASE:
1561 mc->mc_flags &= ~LDAP_BACK_F_CHASE_REFERRALS;
1562 break;
1563
1564 #ifdef SLAPD_META_CLIENT_PR
1565 case LDAP_BACK_CFG_CLIENT_PR:
1566 mc->mc_ps = META_CLIENT_PR_DISABLE;
1567 break;
1568 #endif /* SLAPD_META_CLIENT_PR */
1569
1570 case LDAP_BACK_CFG_DEFAULT_T:
1571 mi->mi_defaulttarget = META_DEFAULT_TARGET_NONE;
1572 break;
1573
1574 case LDAP_BACK_CFG_NETWORK_TIMEOUT:
1575 mc->mc_network_timeout = 0;
1576 break;
1577
1578 case LDAP_BACK_CFG_NOREFS:
1579 mc->mc_flags &= ~LDAP_BACK_F_NOREFS;
1580 break;
1581
1582 case LDAP_BACK_CFG_NOUNDEFFILTER:
1583 mc->mc_flags &= ~LDAP_BACK_F_NOUNDEFFILTER;
1584 break;
1585
1586 case LDAP_BACK_CFG_NRETRIES:
1587 mc->mc_nretries = META_RETRY_DEFAULT;
1588 break;
1589
1590 case LDAP_BACK_CFG_QUARANTINE:
1591 if ( META_BACK_CMN_QUARANTINE( mc )) {
1592 mi->mi_ldap_extra->retry_info_destroy( &mc->mc_quarantine );
1593 mc->mc_flags &= ~LDAP_BACK_F_QUARANTINE;
1594 if ( mc == &mt->mt_mc ) {
1595 ldap_pvt_thread_mutex_destroy( &mt->mt_quarantine_mutex );
1596 mt->mt_isquarantined = 0;
1597 }
1598 }
1599 break;
1600
1601 case LDAP_BACK_CFG_REBIND:
1602 mc->mc_flags &= ~LDAP_BACK_F_SAVECRED;
1603 break;
1604
1605 case LDAP_BACK_CFG_TIMEOUT:
1606 for ( i = 0; i < SLAP_OP_LAST; i++ ) {
1607 mc->mc_timeout[ i ] = 0;
1608 }
1609 break;
1610
1611 case LDAP_BACK_CFG_VERSION:
1612 mc->mc_version = 0;
1613 break;
1614
1615 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
1616 case LDAP_BACK_CFG_ST_REQUEST:
1617 mc->mc_flags &= ~LDAP_BACK_F_ST_REQUEST;
1618 break;
1619 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
1620
1621 case LDAP_BACK_CFG_T_F:
1622 mc->mc_flags &= ~LDAP_BACK_F_T_F_MASK2;
1623 break;
1624
1625 case LDAP_BACK_CFG_TLS:
1626 mc->mc_flags &= ~LDAP_BACK_F_TLS_MASK;
1627 if ( mt )
1628 bindconf_free( &mt->mt_tls );
1629 break;
1630
1631 /* target attrs */
1632 case LDAP_BACK_CFG_URI:
1633 if ( mt->mt_uri ) {
1634 ch_free( mt->mt_uri );
1635 mt->mt_uri = NULL;
1636 }
1637 /* FIXME: should have a way to close all cached
1638 * connections associated with this target.
1639 */
1640 break;
1641
1642 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
1643 BerVarray *bvp;
1644
1645 bvp = &mt->mt_idassert_authz;
1646 if ( c->valx < 0 ) {
1647 if ( *bvp != NULL ) {
1648 ber_bvarray_free( *bvp );
1649 *bvp = NULL;
1650 }
1651
1652 } else {
1653 if ( *bvp == NULL ) {
1654 rc = 1;
1655 break;
1656 }
1657
1658 for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ )
1659 ;
1660
1661 if ( i >= c->valx ) {
1662 rc = 1;
1663 break;
1664 }
1665 ber_memfree( ((*bvp)[ c->valx ]).bv_val );
1666 for ( i = c->valx; !BER_BVISNULL( &((*bvp)[ i + 1 ]) ); i++ ) {
1667 (*bvp)[ i ] = (*bvp)[ i + 1 ];
1668 }
1669 BER_BVZERO( &((*bvp)[ i ]) );
1670 }
1671 } break;
1672
1673 case LDAP_BACK_CFG_IDASSERT_BIND:
1674 bindconf_free( &mt->mt_idassert.si_bc );
1675 memset( &mt->mt_idassert, 0, sizeof( slap_idassert_t ) );
1676 break;
1677
1678 case LDAP_BACK_CFG_SUFFIXM:
1679 if ( mt->mt_lsuffixm.bv_val ) {
1680 ch_free( mt->mt_lsuffixm.bv_val );
1681 ch_free( mt->mt_rsuffixm.bv_val );
1682 BER_BVZERO( &mt->mt_lsuffixm );
1683 BER_BVZERO( &mt->mt_rsuffixm );
1684 }
1685 break;
1686
1687 case LDAP_BACK_CFG_SUBTREE_EX:
1688 case LDAP_BACK_CFG_SUBTREE_IN:
1689 /* can only be one of exclude or include */
1690 if (( c->type == LDAP_BACK_CFG_SUBTREE_EX ) ^ mt->mt_subtree_exclude ) {
1691 rc = 1;
1692 break;
1693 }
1694 if ( c->valx < 0 ) {
1695 asyncmeta_subtree_destroy( mt->mt_subtree );
1696 mt->mt_subtree = NULL;
1697 } else {
1698 a_metasubtree_t *ms, **mprev;
1699 for (i=0, mprev = &mt->mt_subtree, ms = *mprev; ms; ms = *mprev) {
1700 if ( i == c->valx ) {
1701 *mprev = ms->ms_next;
1702 asyncmeta_subtree_free( ms );
1703 break;
1704 }
1705 i++;
1706 mprev = &ms->ms_next;
1707 }
1708 if ( i != c->valx )
1709 rc = 1;
1710 }
1711 break;
1712
1713 case LDAP_BACK_CFG_FILTER:
1714 if ( c->valx < 0 ) {
1715 asyncmeta_filter_destroy( mt->mt_filter );
1716 mt->mt_filter = NULL;
1717 } else {
1718 metafilter_t *mf, **mprev;
1719 for (i=0, mprev = &mt->mt_filter, mf = *mprev; mf; mf = *mprev) {
1720 if ( i == c->valx ) {
1721 *mprev = mf->mf_next;
1722 asyncmeta_filter_free( mf );
1723 break;
1724 }
1725 i++;
1726 mprev = &mf->mf_next;
1727 }
1728 if ( i != c->valx )
1729 rc = 1;
1730 }
1731 break;
1732 case LDAP_BACK_CFG_MAX_PENDING_OPS:
1733 mi->mi_max_pending_ops = 0;
1734 break;
1735
1736 case LDAP_BACK_CFG_MAX_TARGET_CONNS:
1737 mi->mi_max_target_conns = 0;
1738 break;
1739
1740 case LDAP_BACK_CFG_MAX_TIMEOUT_OPS:
1741 mi->mi_max_timeout_ops = 0;
1742 break;
1743
1744 case LDAP_BACK_CFG_KEEPALIVE:
1745 mt->mt_tls.sb_keepalive.sk_idle = 0;
1746 mt->mt_tls.sb_keepalive.sk_probes = 0;
1747 mt->mt_tls.sb_keepalive.sk_interval = 0;
1748 break;
1749
1750 case LDAP_BACK_CFG_TCP_USER_TIMEOUT:
1751 mt->mt_tls.sb_tcp_user_timeout = 0;
1752 break;
1753
1754 default:
1755 rc = 1;
1756 break;
1757 }
1758
1759 return rc;
1760 }
1761
1762 if ( c->op == SLAP_CONFIG_ADD ) {
1763 if ( c->type >= LDAP_BACK_CFG_LAST_BASE ) {
1764 /* exclude CFG_URI from this check */
1765 if ( c->type > LDAP_BACK_CFG_LAST_BOTH ) {
1766 if ( !mi->mi_ntargets ) {
1767 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1768 "need \"uri\" directive first" );
1769 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1770 return 1;
1771 }
1772 }
1773 if ( mi->mi_ntargets ) {
1774 mt = mi->mi_targets[ mi->mi_ntargets-1 ];
1775 mc = &mt->mt_mc;
1776 } else {
1777 mt = NULL;
1778 mc = &mi->mi_mc;
1779 }
1780 }
1781 } else {
1782 if ( c->table == Cft_Database ) {
1783 mt = NULL;
1784 mc = &mi->mi_mc;
1785 } else {
1786 mt = c->ca_private;
1787 if ( mt )
1788 mc = &mt->mt_mc;
1789 else
1790 mc = NULL;
1791 }
1792 }
1793
1794 switch( c->type ) {
1795 case LDAP_BACK_CFG_URI: {
1796 LDAPURLDesc *ludp;
1797 struct berval dn;
1798 int j;
1799
1800 char **uris = NULL;
1801
1802 if ( c->be->be_nsuffix == NULL ) {
1803 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1804 "the suffix must be defined before any target" );
1805 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1806 return 1;
1807 }
1808
1809 i = mi->mi_ntargets++;
1810
1811 mi->mi_targets = ( a_metatarget_t ** )ch_realloc( mi->mi_targets,
1812 sizeof( a_metatarget_t * ) * mi->mi_ntargets );
1813 if ( mi->mi_targets == NULL ) {
1814 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1815 "out of memory while storing server name"
1816 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
1817 c->argv[0] );
1818 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1819 return 1;
1820 }
1821
1822 if ( asyncmeta_back_new_target( &mi->mi_targets[ i ] ) != 0 ) {
1823 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1824 "unable to init server"
1825 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
1826 c->argv[0] );
1827 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1828 return 1;
1829 }
1830
1831 mt = mi->mi_targets[ i ];
1832
1833 mt->mt_rebind_f = mi->mi_rebind_f;
1834 mt->mt_urllist_f = mi->mi_urllist_f;
1835 mt->mt_urllist_p = mt;
1836
1837 if ( META_BACK_QUARANTINE( mi ) ) {
1838 ldap_pvt_thread_mutex_init( &mt->mt_quarantine_mutex );
1839 }
1840 mt->mt_mc = mi->mi_mc;
1841
1842 for ( j = 1; j < c->argc; j++ ) {
1843 char **tmpuris = ldap_str2charray( c->argv[ j ], "\t" );
1844
1845 if ( tmpuris == NULL ) {
1846 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1847 "unable to parse URIs #%d"
1848 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
1849 j-1, c->argv[0] );
1850 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1851 return 1;
1852 }
1853
1854 if ( j == 1 ) {
1855 uris = tmpuris;
1856
1857 } else {
1858 ldap_charray_merge( &uris, tmpuris );
1859 ldap_charray_free( tmpuris );
1860 }
1861 }
1862
1863 for ( j = 0; uris[ j ] != NULL; j++ ) {
1864 char *tmpuri = NULL;
1865
1866 /*
1867 * uri MUST be legal!
1868 */
1869 if ( ldap_url_parselist_ext( &ludp, uris[ j ], "\t",
1870 LDAP_PVT_URL_PARSE_NONE ) != LDAP_SUCCESS
1871 || ludp->lud_next != NULL )
1872 {
1873 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1874 "unable to parse URI #%d"
1875 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
1876 j-1, c->argv[0] );
1877 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1878 ldap_charray_free( uris );
1879 return 1;
1880 }
1881
1882 if ( j == 0 ) {
1883
1884 /*
1885 * uri MUST have the <dn> part!
1886 */
1887 if ( ludp->lud_dn == NULL ) {
1888 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1889 "missing <naming context> "
1890 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
1891 c->argv[0] );
1892 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1893 ldap_free_urllist( ludp );
1894 ldap_charray_free( uris );
1895 return 1;
1896 }
1897
1898 /*
1899 * copies and stores uri and suffix
1900 */
1901 ber_str2bv( ludp->lud_dn, 0, 0, &dn );
1902 rc = dnPrettyNormal( NULL, &dn, &mt->mt_psuffix,
1903 &mt->mt_nsuffix, NULL );
1904 if ( rc != LDAP_SUCCESS ) {
1905 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1906 "target DN is invalid \"%s\"",
1907 c->argv[1] );
1908 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1909 ldap_free_urllist( ludp );
1910 ldap_charray_free( uris );
1911 return( 1 );
1912 }
1913
1914 ludp->lud_dn[ 0 ] = '\0';
1915
1916 switch ( ludp->lud_scope ) {
1917 case LDAP_SCOPE_DEFAULT:
1918 mt->mt_scope = LDAP_SCOPE_SUBTREE;
1919 break;
1920
1921 case LDAP_SCOPE_SUBTREE:
1922 case LDAP_SCOPE_SUBORDINATE:
1923 mt->mt_scope = ludp->lud_scope;
1924 break;
1925
1926 default:
1927 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1928 "invalid scope for target \"%s\"",
1929 c->argv[1] );
1930 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1931 ldap_free_urllist( ludp );
1932 ldap_charray_free( uris );
1933 return( 1 );
1934 }
1935
1936 } else {
1937 /* check all, to apply the scope check on the first one */
1938 if ( ludp->lud_dn != NULL && ludp->lud_dn[ 0 ] != '\0' ) {
1939 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1940 "multiple URIs must have no DN part" );
1941 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1942 ldap_free_urllist( ludp );
1943 ldap_charray_free( uris );
1944 return( 1 );
1945
1946 }
1947 }
1948
1949 tmpuri = ldap_url_list2urls( ludp );
1950 ldap_free_urllist( ludp );
1951 if ( tmpuri == NULL ) {
1952 snprintf( c->cr_msg, sizeof( c->cr_msg ), "no memory?" );
1953 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1954 ldap_charray_free( uris );
1955 return( 1 );
1956 }
1957 ldap_memfree( uris[ j ] );
1958 uris[ j ] = tmpuri;
1959 }
1960
1961 mt->mt_uri = ldap_charray2str( uris, " " );
1962 ldap_charray_free( uris );
1963 if ( mt->mt_uri == NULL) {
1964 snprintf( c->cr_msg, sizeof( c->cr_msg ), "no memory?" );
1965 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1966 return( 1 );
1967 }
1968
1969 /*
1970 * uri MUST be a branch of suffix!
1971 */
1972 for ( j = 0; !BER_BVISNULL( &c->be->be_nsuffix[ j ] ); j++ ) {
1973 if ( dnIsSuffix( &mt->mt_nsuffix, &c->be->be_nsuffix[ j ] ) ) {
1974 break;
1975 }
1976 }
1977
1978 if ( BER_BVISNULL( &c->be->be_nsuffix[ j ] ) ) {
1979 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1980 "<naming context> of URI must be within the naming context of this database." );
1981 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1982 return 1;
1983 }
1984 c->ca_private = mt;
1985 config_push_cleanup( c, asyncmeta_cf_cleanup );
1986 } break;
1987 case LDAP_BACK_CFG_SUBTREE_EX:
1988 case LDAP_BACK_CFG_SUBTREE_IN:
1989 /* subtree-exclude */
1990 if ( asyncmeta_subtree_config( mt, c )) {
1991 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1992 return 1;
1993 }
1994 break;
1995
1996 case LDAP_BACK_CFG_FILTER: {
1997 metafilter_t *mf, **m2;
1998 mf = ch_malloc( sizeof( metafilter_t ));
1999 rc = regcomp( &mf->mf_regex, c->argv[1], REG_EXTENDED );
2000 if ( rc ) {
2001 char regerr[ SLAP_TEXT_BUFLEN ];
2002 regerror( rc, &mf->mf_regex, regerr, sizeof(regerr) );
2003 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2004 "regular expression \"%s\" bad because of %s",
2005 c->argv[1], regerr );
2006 ch_free( mf );
2007 return 1;
2008 }
2009 ber_str2bv( c->argv[1], 0, 1, &mf->mf_regex_pattern );
2010 for ( m2 = &mt->mt_filter; *m2; m2 = &(*m2)->mf_next )
2011 ;
2012 *m2 = mf;
2013 } break;
2014 case LDAP_BACK_CFG_MAX_PENDING_OPS:
2015 if (c->value_int < 0) {
2016 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2017 "max-pending-ops invalid value %d",
2018 c->value_int);
2019 return 1;
2020 }
2021 mi->mi_max_pending_ops = c->value_int;
2022 break;
2023 case LDAP_BACK_CFG_MAX_TARGET_CONNS:
2024 {
2025 if (c->value_int < 0) {
2026 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2027 "max-target-conns invalid value %d",
2028 c->value_int);
2029 return 1;
2030 }
2031 mi->mi_max_target_conns = c->value_int;
2032 }
2033 break;
2034 case LDAP_BACK_CFG_MAX_TIMEOUT_OPS:
2035 if (c->value_int < 0) {
2036 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2037 "max-timeout-ops invalid value %d",
2038 c->value_int);
2039 return 1;
2040 }
2041 mi->mi_max_timeout_ops = c->value_int;
2042 break;
2043
2044 case LDAP_BACK_CFG_DEFAULT_T:
2045 /* default target directive */
2046 i = mi->mi_ntargets - 1;
2047
2048 if ( c->argc == 1 ) {
2049 if ( i < 0 ) {
2050 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2051 "\"%s\" alone must be inside a \"uri\" directive",
2052 c->argv[0] );
2053 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2054 return 1;
2055 }
2056 mi->mi_defaulttarget = i;
2057
2058 } else {
2059 if ( strcasecmp( c->argv[ 1 ], "none" ) == 0 ) {
2060 if ( i >= 0 ) {
2061 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2062 "\"%s none\" should go before uri definitions",
2063 c->argv[0] );
2064 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2065 }
2066 mi->mi_defaulttarget = META_DEFAULT_TARGET_NONE;
2067
2068 } else {
2069
2070 if ( lutil_atoi( &mi->mi_defaulttarget, c->argv[ 1 ] ) != 0
2071 || mi->mi_defaulttarget < 0
2072 || mi->mi_defaulttarget >= i - 1 )
2073 {
2074 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2075 "illegal target number %d",
2076 mi->mi_defaulttarget );
2077 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2078 return 1;
2079 }
2080 }
2081 }
2082 break;
2083
2084 case LDAP_BACK_CFG_DNCACHE_TTL:
2085 /* ttl of dn cache */
2086 if ( strcasecmp( c->argv[ 1 ], "forever" ) == 0 ) {
2087 mi->mi_cache.ttl = META_DNCACHE_FOREVER;
2088
2089 } else if ( strcasecmp( c->argv[ 1 ], "disabled" ) == 0 ) {
2090 mi->mi_cache.ttl = META_DNCACHE_DISABLED;
2091
2092 } else {
2093 unsigned long t;
2094
2095 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
2096 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2097 "unable to parse dncache ttl \"%s\"",
2098 c->argv[ 1 ] );
2099 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2100 return 1;
2101 }
2102 mi->mi_cache.ttl = (time_t)t;
2103 }
2104 break;
2105
2106 case LDAP_BACK_CFG_NETWORK_TIMEOUT: {
2107 /* network timeout when connecting to ldap servers */
2108 unsigned long t;
2109
2110 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) {
2111 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2112 "unable to parse network timeout \"%s\"",
2113 c->argv[ 1 ] );
2114 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2115 return 1;
2116 }
2117 mc->mc_network_timeout = (time_t)t;
2118 } break;
2119
2120 case LDAP_BACK_CFG_IDLE_TIMEOUT: {
2121 /* idle timeout when connecting to ldap servers */
2122 unsigned long t;
2123
2124 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) {
2125 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2126 "unable to parse idle timeout \"%s\"",
2127 c->argv[ 1 ] );
2128 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2129 return 1;
2130
2131 }
2132 mi->mi_idle_timeout = (time_t)t;
2133 } break;
2134
2135 case LDAP_BACK_CFG_BIND_TIMEOUT:
2136 /* bind timeout when connecting to ldap servers */
2137 mc->mc_bind_timeout.tv_sec = c->value_ulong/1000000;
2138 mc->mc_bind_timeout.tv_usec = c->value_ulong%1000000;
2139 break;
2140
2141 case LDAP_BACK_CFG_REBIND:
2142 /* save bind creds for referral rebinds? */
2143 if ( c->argc == 1 || c->value_int ) {
2144 mc->mc_flags |= LDAP_BACK_F_SAVECRED;
2145 } else {
2146 mc->mc_flags &= ~LDAP_BACK_F_SAVECRED;
2147 }
2148 break;
2149
2150 case LDAP_BACK_CFG_CHASE:
2151 if ( c->argc == 1 || c->value_int ) {
2152 mc->mc_flags |= LDAP_BACK_F_CHASE_REFERRALS;
2153 } else {
2154 mc->mc_flags &= ~LDAP_BACK_F_CHASE_REFERRALS;
2155 }
2156 break;
2157
2158 case LDAP_BACK_CFG_TLS:
2159 i = verb_to_mask( c->argv[1], tls_mode );
2160 if ( BER_BVISNULL( &tls_mode[i].word ) ) {
2161 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2162 "%s unknown argument \"%s\"",
2163 c->argv[0], c->argv[1] );
2164 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2165 return 1;
2166 }
2167 mc->mc_flags &= ~LDAP_BACK_F_TLS_MASK;
2168 mc->mc_flags |= tls_mode[i].mask;
2169
2170 if ( c->argc > 2 ) {
2171 if ( c->op == SLAP_CONFIG_ADD && mi->mi_ntargets == 0 ) {
2172 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2173 "need \"uri\" directive first" );
2174 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2175 return 1;
2176 }
2177
2178 for ( i = 2; i < c->argc; i++ ) {
2179 if ( bindconf_tls_parse( c->argv[i], &mt->mt_tls ))
2180 return 1;
2181 }
2182 bindconf_tls_defaults( &mt->mt_tls );
2183 }
2184 break;
2185
2186 case LDAP_BACK_CFG_T_F:
2187 i = verb_to_mask( c->argv[1], t_f_mode );
2188 if ( BER_BVISNULL( &t_f_mode[i].word ) ) {
2189 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2190 "%s unknown argument \"%s\"",
2191 c->argv[0], c->argv[1] );
2192 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2193 return 1;
2194 }
2195 mc->mc_flags &= ~LDAP_BACK_F_T_F_MASK2;
2196 mc->mc_flags |= t_f_mode[i].mask;
2197 break;
2198
2199 case LDAP_BACK_CFG_ONERR:
2200 /* onerr? */
2201 i = verb_to_mask( c->argv[1], onerr_mode );
2202 if ( BER_BVISNULL( &onerr_mode[i].word ) ) {
2203 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2204 "%s unknown argument \"%s\"",
2205 c->argv[0], c->argv[1] );
2206 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2207 return 1;
2208 }
2209 mi->mi_flags &= ~META_BACK_F_ONERR_MASK;
2210 mi->mi_flags |= onerr_mode[i].mask;
2211 break;
2212
2213 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER:
2214 /* bind-defer? */
2215 if ( c->argc == 1 || c->value_int ) {
2216 mi->mi_flags |= META_BACK_F_DEFER_ROOTDN_BIND;
2217 } else {
2218 mi->mi_flags &= ~META_BACK_F_DEFER_ROOTDN_BIND;
2219 }
2220 break;
2221
2222 case LDAP_BACK_CFG_CONNPOOLMAX:
2223 /* privileged connections pool max size ? */
2224 if ( mi->mi_ntargets > 0 ) {
2225 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2226 "\"%s\" must appear before target definitions",
2227 c->argv[0] );
2228 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2229 return( 1 );
2230 }
2231
2232 if ( c->value_int < LDAP_BACK_CONN_PRIV_MIN
2233 || c->value_int > LDAP_BACK_CONN_PRIV_MAX )
2234 {
2235 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2236 "invalid max size " "of privileged "
2237 "connections pool \"%s\" "
2238 "in \"conn-pool-max <n> "
2239 "(must be between %d and %d)\"",
2240 c->argv[ 1 ],
2241 LDAP_BACK_CONN_PRIV_MIN,
2242 LDAP_BACK_CONN_PRIV_MAX );
2243 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2244 return 1;
2245 }
2246 mi->mi_conn_priv_max = c->value_int;
2247 break;
2248
2249 case LDAP_BACK_CFG_CANCEL:
2250 i = verb_to_mask( c->argv[1], cancel_mode );
2251 if ( BER_BVISNULL( &cancel_mode[i].word ) ) {
2252 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2253 "%s unknown argument \"%s\"",
2254 c->argv[0], c->argv[1] );
2255 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2256 return 1;
2257 }
2258 mc->mc_flags &= ~LDAP_BACK_F_CANCEL_MASK2;
2259 mc->mc_flags |= cancel_mode[i].mask;
2260 break;
2261
2262 case LDAP_BACK_CFG_TIMEOUT:
2263 for ( i = 1; i < c->argc; i++ ) {
2264 if ( isdigit( (unsigned char) c->argv[ i ][ 0 ] ) ) {
2265 int j;
2266 unsigned u;
2267
2268 if ( lutil_atoux( &u, c->argv[ i ], 0 ) != 0 ) {
2269 snprintf( c->cr_msg, sizeof( c->cr_msg),
2270 "unable to parse timeout \"%s\"",
2271 c->argv[ i ] );
2272 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2273 return 1;
2274 }
2275
2276 for ( j = 0; j < SLAP_OP_LAST; j++ ) {
2277 mc->mc_timeout[ j ] = u;
2278 }
2279
2280 continue;
2281 }
2282
2283 if ( slap_cf_aux_table_parse( c->argv[ i ], mc->mc_timeout, timeout_table, "slapd-meta timeout" ) ) {
2284 snprintf( c->cr_msg, sizeof( c->cr_msg),
2285 "unable to parse timeout \"%s\"",
2286 c->argv[ i ] );
2287 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2288 return 1;
2289 }
2290 }
2291 break;
2292
2293 case LDAP_BACK_CFG_IDASSERT_BIND:
2294 /* idassert-bind */
2295 rc = mi->mi_ldap_extra->idassert_parse( c, &mt->mt_idassert );
2296 break;
2297
2298 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM:
2299 /* idassert-authzFrom */
2300 rc = mi->mi_ldap_extra->idassert_authzfrom_parse( c, &mt->mt_idassert );
2301 break;
2302
2303 case LDAP_BACK_CFG_QUARANTINE:
2304 /* quarantine */
2305 if ( META_BACK_CMN_QUARANTINE( mc ) )
2306 {
2307 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2308 "quarantine already defined" );
2309 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2310 return 1;
2311 }
2312
2313 if ( mt ) {
2314 mc->mc_quarantine.ri_interval = NULL;
2315 mc->mc_quarantine.ri_num = NULL;
2316 if ( !META_BACK_QUARANTINE( mi ) ) {
2317 ldap_pvt_thread_mutex_init( &mt->mt_quarantine_mutex );
2318 }
2319 }
2320
2321 if ( mi->mi_ldap_extra->retry_info_parse( c->argv[ 1 ], &mc->mc_quarantine, c->cr_msg, sizeof( c->cr_msg ) ) ) {
2322 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2323 return 1;
2324 }
2325
2326 mc->mc_flags |= LDAP_BACK_F_QUARANTINE;
2327 break;
2328
2329 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
2330 case LDAP_BACK_CFG_ST_REQUEST:
2331 /* session tracking request */
2332 if ( c->value_int ) {
2333 mc->mc_flags |= LDAP_BACK_F_ST_REQUEST;
2334 } else {
2335 mc->mc_flags &= ~LDAP_BACK_F_ST_REQUEST;
2336 }
2337 break;
2338 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
2339
2340 case LDAP_BACK_CFG_SUFFIXM:
2341 rc = asyncmeta_suffixm_config( c, c->argc, c->argv, mt );
2342 break;
2343
2344 case LDAP_BACK_CFG_NRETRIES: {
2345 int nretries = META_RETRY_UNDEFINED;
2346
2347 if ( strcasecmp( c->argv[ 1 ], "forever" ) == 0 ) {
2348 nretries = META_RETRY_FOREVER;
2349
2350 } else if ( strcasecmp( c->argv[ 1 ], "never" ) == 0 ) {
2351 nretries = META_RETRY_NEVER;
2352
2353 } else {
2354 if ( lutil_atoi( &nretries, c->argv[ 1 ] ) != 0 ) {
2355 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2356 "unable to parse nretries {never|forever|<retries>}: \"%s\"",
2357 c->argv[ 1 ] );
2358 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2359 return 1;
2360 }
2361 }
2362
2363 mc->mc_nretries = nretries;
2364 } break;
2365
2366 case LDAP_BACK_CFG_VERSION:
2367 if ( c->value_int != 0 && ( c->value_int < LDAP_VERSION_MIN || c->value_int > LDAP_VERSION_MAX ) ) {
2368 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2369 "unsupported protocol version \"%s\"",
2370 c->argv[ 1 ] );
2371 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2372 return 1;
2373 }
2374 mc->mc_version = c->value_int;
2375 break;
2376
2377 case LDAP_BACK_CFG_NOREFS:
2378 /* do not return search references */
2379 if ( c->value_int ) {
2380 mc->mc_flags |= LDAP_BACK_F_NOREFS;
2381 } else {
2382 mc->mc_flags &= ~LDAP_BACK_F_NOREFS;
2383 }
2384 break;
2385
2386 case LDAP_BACK_CFG_NOUNDEFFILTER:
2387 /* do not propagate undefined search filters */
2388 if ( c->value_int ) {
2389 mc->mc_flags |= LDAP_BACK_F_NOUNDEFFILTER;
2390 } else {
2391 mc->mc_flags &= ~LDAP_BACK_F_NOUNDEFFILTER;
2392 }
2393 break;
2394
2395 #ifdef SLAPD_META_CLIENT_PR
2396 case LDAP_BACK_CFG_CLIENT_PR:
2397 if ( strcasecmp( c->argv[ 1 ], "accept-unsolicited" ) == 0 ) {
2398 mc->mc_ps = META_CLIENT_PR_ACCEPT_UNSOLICITED;
2399
2400 } else if ( strcasecmp( c->argv[ 1 ], "disable" ) == 0 ) {
2401 mc->mc_ps = META_CLIENT_PR_DISABLE;
2402
2403 } else if ( lutil_atoi( &mc->mc_ps, c->argv[ 1 ] ) || mc->mc_ps < -1 ) {
2404 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2405 "unable to parse client-pr {accept-unsolicited|disable|<size>}: \"%s\"",
2406 c->argv[ 1 ] );
2407 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2408 return( 1 );
2409 }
2410 break;
2411 #endif /* SLAPD_META_CLIENT_PR */
2412
2413 case LDAP_BACK_CFG_KEEPALIVE:
2414 slap_keepalive_parse( ber_bvstrdup(c->argv[1]),
2415 &mt->mt_tls.sb_keepalive, 0, 0, 0);
2416 break;
2417
2418 case LDAP_BACK_CFG_TCP_USER_TIMEOUT:
2419 mt->mt_tls.sb_tcp_user_timeout = c->value_uint;
2420 break;
2421
2422 /* anything else */
2423 default:
2424 return SLAP_CONF_UNKNOWN;
2425 }
2426
2427 return rc;
2428 }
2429
2430 int
asyncmeta_back_init_cf(BackendInfo * bi)2431 asyncmeta_back_init_cf( BackendInfo *bi )
2432 {
2433 int rc;
2434
2435 /* Make sure we don't exceed the bits reserved for userland */
2436 config_check_userland( LDAP_BACK_CFG_LAST );
2437
2438 bi->bi_cf_ocs = a_metaocs;
2439
2440 rc = config_register_schema( a_metacfg, a_metaocs );
2441 if ( rc ) {
2442 return rc;
2443 }
2444
2445 return 0;
2446 }
2447