1 /* $NetBSD: config.c,v 1.3 2021/08/14 16:15:00 christos Exp $ */
2
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1999-2021 The OpenLDAP Foundation.
7 * Portions Copyright 2001-2003 Pierangelo Masarati.
8 * Portions Copyright 1999-2003 Howard Chu.
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 /* ACKNOWLEDGEMENTS:
20 * This work was initially developed by the Howard Chu for inclusion
21 * in OpenLDAP Software and subsequently enhanced by Pierangelo
22 * Masarati.
23 */
24
25 #include <sys/cdefs.h>
26 __RCSID("$NetBSD: config.c,v 1.3 2021/08/14 16:15:00 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-meta.h"
42
43 #ifdef LDAP_DEVEL
44 #define SLAP_AUTH_DN 1
45 #endif
46
47 static ConfigDriver meta_back_cf_gen;
48 static ConfigLDAPadd meta_ldadd;
49 static ConfigCfAdd meta_cfadd;
50
51 static int ldap_back_map_config(
52 ConfigArgs *c,
53 struct ldapmap *oc_map,
54 struct ldapmap *at_map );
55
56 /* Three sets of enums:
57 * 1) attrs that are only valid in the base config
58 * 2) attrs that are valid in base or target
59 * 3) attrs that are only valid in a target
60 */
61
62 /* Base attrs */
63 enum {
64 LDAP_BACK_CFG_CONN_TTL = 1,
65 LDAP_BACK_CFG_DNCACHE_TTL,
66 LDAP_BACK_CFG_IDLE_TIMEOUT,
67 LDAP_BACK_CFG_ONERR,
68 LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER,
69 LDAP_BACK_CFG_SINGLECONN,
70 LDAP_BACK_CFG_USETEMP,
71 LDAP_BACK_CFG_CONNPOOLMAX,
72 LDAP_BACK_CFG_LAST_BASE
73 };
74
75 /* Base or target */
76 enum {
77 LDAP_BACK_CFG_BIND_TIMEOUT = LDAP_BACK_CFG_LAST_BASE,
78 LDAP_BACK_CFG_CANCEL,
79 LDAP_BACK_CFG_CHASE,
80 LDAP_BACK_CFG_CLIENT_PR,
81 LDAP_BACK_CFG_DEFAULT_T,
82 LDAP_BACK_CFG_NETWORK_TIMEOUT,
83 LDAP_BACK_CFG_NOREFS,
84 LDAP_BACK_CFG_NOUNDEFFILTER,
85 LDAP_BACK_CFG_NRETRIES,
86 LDAP_BACK_CFG_QUARANTINE,
87 LDAP_BACK_CFG_REBIND,
88 LDAP_BACK_CFG_TIMEOUT,
89 LDAP_BACK_CFG_VERSION,
90 LDAP_BACK_CFG_ST_REQUEST,
91 LDAP_BACK_CFG_T_F,
92 LDAP_BACK_CFG_TLS,
93 LDAP_BACK_CFG_LAST_BOTH
94 };
95
96 /* Target attrs */
97 enum {
98 LDAP_BACK_CFG_URI = LDAP_BACK_CFG_LAST_BOTH,
99 LDAP_BACK_CFG_IDASSERT_AUTHZFROM,
100 LDAP_BACK_CFG_IDASSERT_BIND,
101 LDAP_BACK_CFG_REWRITE,
102 LDAP_BACK_CFG_SUFFIXM,
103 LDAP_BACK_CFG_MAP,
104 LDAP_BACK_CFG_SUBTREE_EX,
105 LDAP_BACK_CFG_SUBTREE_IN,
106 LDAP_BACK_CFG_PSEUDOROOTDN,
107 LDAP_BACK_CFG_PSEUDOROOTPW,
108 LDAP_BACK_CFG_KEEPALIVE,
109 LDAP_BACK_CFG_TCP_USER_TIMEOUT,
110 LDAP_BACK_CFG_FILTER,
111
112 LDAP_BACK_CFG_LAST
113 };
114
115 static ConfigTable metacfg[] = {
116 { "uri", "uri", 2, 0, 0,
117 ARG_MAGIC|LDAP_BACK_CFG_URI,
118 meta_back_cf_gen, "( OLcfgDbAt:0.14 "
119 "NAME 'olcDbURI' "
120 "DESC 'URI (list) for remote DSA' "
121 "EQUALITY caseExactMatch "
122 "SYNTAX OMsDirectoryString "
123 "SINGLE-VALUE )",
124 NULL, NULL },
125 { "tls", "what", 2, 0, 0,
126 ARG_MAGIC|LDAP_BACK_CFG_TLS,
127 meta_back_cf_gen, "( OLcfgDbAt:3.1 "
128 "NAME 'olcDbStartTLS' "
129 "DESC 'StartTLS' "
130 "EQUALITY caseExactMatch "
131 "SYNTAX OMsDirectoryString "
132 "SINGLE-VALUE )",
133 NULL, NULL },
134 { "idassert-bind", "args", 2, 0, 0,
135 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND,
136 meta_back_cf_gen, "( OLcfgDbAt:3.7 "
137 "NAME 'olcDbIDAssertBind' "
138 "DESC 'Remote Identity Assertion administrative identity auth bind configuration' "
139 "EQUALITY caseIgnoreMatch "
140 "SYNTAX OMsDirectoryString "
141 "SINGLE-VALUE )",
142 NULL, NULL },
143 { "idassert-authzFrom", "authzRule", 2, 2, 0,
144 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHZFROM,
145 meta_back_cf_gen, "( OLcfgDbAt:3.9 "
146 "NAME 'olcDbIDAssertAuthzFrom' "
147 "DESC 'Remote Identity Assertion authz rules' "
148 "EQUALITY caseIgnoreMatch "
149 "SYNTAX OMsDirectoryString "
150 "X-ORDERED 'VALUES' )",
151 NULL, NULL },
152 { "rebind-as-user", "true|FALSE", 1, 2, 0,
153 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND,
154 meta_back_cf_gen, "( OLcfgDbAt:3.10 "
155 "NAME 'olcDbRebindAsUser' "
156 "DESC 'Rebind as user' "
157 "EQUALITY booleanMatch "
158 "SYNTAX OMsBoolean "
159 "SINGLE-VALUE )",
160 NULL, NULL },
161 { "chase-referrals", "true|FALSE", 2, 2, 0,
162 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE,
163 meta_back_cf_gen, "( OLcfgDbAt:3.11 "
164 "NAME 'olcDbChaseReferrals' "
165 "DESC 'Chase referrals' "
166 "EQUALITY booleanMatch "
167 "SYNTAX OMsBoolean "
168 "SINGLE-VALUE )",
169 NULL, NULL },
170 { "t-f-support", "true|FALSE|discover", 2, 2, 0,
171 ARG_MAGIC|LDAP_BACK_CFG_T_F,
172 meta_back_cf_gen, "( OLcfgDbAt:3.12 "
173 "NAME 'olcDbTFSupport' "
174 "DESC 'Absolute filters support' "
175 "EQUALITY caseIgnoreMatch "
176 "SYNTAX OMsDirectoryString "
177 "SINGLE-VALUE )",
178 NULL, NULL },
179 { "timeout", "timeout(list)", 2, 0, 0,
180 ARG_MAGIC|LDAP_BACK_CFG_TIMEOUT,
181 meta_back_cf_gen, "( OLcfgDbAt:3.14 "
182 "NAME 'olcDbTimeout' "
183 "DESC 'Per-operation timeouts' "
184 "EQUALITY caseIgnoreMatch "
185 "SYNTAX OMsDirectoryString "
186 "SINGLE-VALUE )",
187 NULL, NULL },
188 { "idle-timeout", "timeout", 2, 2, 0,
189 ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT,
190 meta_back_cf_gen, "( OLcfgDbAt:3.15 "
191 "NAME 'olcDbIdleTimeout' "
192 "DESC 'connection idle timeout' "
193 "EQUALITY caseIgnoreMatch "
194 "SYNTAX OMsDirectoryString "
195 "SINGLE-VALUE )",
196 NULL, NULL },
197 { "conn-ttl", "ttl", 2, 2, 0,
198 ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL,
199 meta_back_cf_gen, "( OLcfgDbAt:3.16 "
200 "NAME 'olcDbConnTtl' "
201 "DESC 'connection ttl' "
202 "EQUALITY caseIgnoreMatch "
203 "SYNTAX OMsDirectoryString "
204 "SINGLE-VALUE )",
205 NULL, NULL },
206 { "network-timeout", "timeout", 2, 2, 0,
207 ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT,
208 meta_back_cf_gen, "( OLcfgDbAt:3.17 "
209 "NAME 'olcDbNetworkTimeout' "
210 "DESC 'connection network timeout' "
211 "SYNTAX OMsDirectoryString "
212 "SINGLE-VALUE )",
213 NULL, NULL },
214 { "protocol-version", "version", 2, 2, 0,
215 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION,
216 meta_back_cf_gen, "( OLcfgDbAt:3.18 "
217 "NAME 'olcDbProtocolVersion' "
218 "DESC 'protocol version' "
219 "EQUALITY integerMatch "
220 "SYNTAX OMsInteger "
221 "SINGLE-VALUE )",
222 NULL, NULL },
223 { "single-conn", "true|FALSE", 2, 2, 0,
224 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN,
225 meta_back_cf_gen, "( OLcfgDbAt:3.19 "
226 "NAME 'olcDbSingleConn' "
227 "DESC 'cache a single connection per identity' "
228 "EQUALITY booleanMatch "
229 "SYNTAX OMsBoolean "
230 "SINGLE-VALUE )",
231 NULL, NULL },
232 { "cancel", "ABANDON|ignore|exop", 2, 2, 0,
233 ARG_MAGIC|LDAP_BACK_CFG_CANCEL,
234 meta_back_cf_gen, "( OLcfgDbAt:3.20 "
235 "NAME 'olcDbCancel' "
236 "DESC 'abandon/ignore/exop operations when appropriate' "
237 "EQUALITY caseIgnoreMatch "
238 "SYNTAX OMsDirectoryString "
239 "SINGLE-VALUE )",
240 NULL, NULL },
241 { "quarantine", "retrylist", 2, 2, 0,
242 ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE,
243 meta_back_cf_gen, "( OLcfgDbAt:3.21 "
244 "NAME 'olcDbQuarantine' "
245 "DESC 'Quarantine database if connection fails and retry according to rule' "
246 "EQUALITY caseIgnoreMatch "
247 "SYNTAX OMsDirectoryString "
248 "SINGLE-VALUE )",
249 NULL, NULL },
250 { "use-temporary-conn", "true|FALSE", 2, 2, 0,
251 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_USETEMP,
252 meta_back_cf_gen, "( OLcfgDbAt:3.22 "
253 "NAME 'olcDbUseTemporaryConn' "
254 "DESC 'Use temporary connections if the cached one is busy' "
255 "EQUALITY booleanMatch "
256 "SYNTAX OMsBoolean "
257 "SINGLE-VALUE )",
258 NULL, NULL },
259 { "conn-pool-max", "<n>", 2, 2, 0,
260 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX,
261 meta_back_cf_gen, "( OLcfgDbAt:3.23 "
262 "NAME 'olcDbConnectionPoolMax' "
263 "DESC 'Max size of privileged connections pool' "
264 "EQUALITY integerMatch "
265 "SYNTAX OMsInteger "
266 "SINGLE-VALUE )",
267 NULL, NULL },
268 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
269 { "session-tracking-request", "true|FALSE", 2, 2, 0,
270 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_ST_REQUEST,
271 meta_back_cf_gen, "( OLcfgDbAt:3.24 "
272 "NAME 'olcDbSessionTrackingRequest' "
273 "DESC 'Add session tracking control to proxied requests' "
274 "EQUALITY booleanMatch "
275 "SYNTAX OMsBoolean "
276 "SINGLE-VALUE )",
277 NULL, NULL },
278 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
279 { "norefs", "true|FALSE", 2, 2, 0,
280 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOREFS,
281 meta_back_cf_gen, "( OLcfgDbAt:3.25 "
282 "NAME 'olcDbNoRefs' "
283 "DESC 'Do not return search reference responses' "
284 "EQUALITY booleanMatch "
285 "SYNTAX OMsBoolean "
286 "SINGLE-VALUE )",
287 NULL, NULL },
288 { "noundeffilter", "true|FALSE", 2, 2, 0,
289 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOUNDEFFILTER,
290 meta_back_cf_gen, "( OLcfgDbAt:3.26 "
291 "NAME 'olcDbNoUndefFilter' "
292 "DESC 'Do not propagate undefined search filters' "
293 "EQUALITY booleanMatch "
294 "SYNTAX OMsBoolean "
295 "SINGLE-VALUE )",
296 NULL, NULL },
297
298 { "rewrite", "arglist", 2, 0, STRLENOF( "rewrite" ),
299 ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
300 meta_back_cf_gen, "( OLcfgDbAt:3.101 "
301 "NAME 'olcDbRewrite' "
302 "DESC 'DN rewriting rules' "
303 "EQUALITY caseIgnoreMatch "
304 "SYNTAX OMsDirectoryString "
305 "X-ORDERED 'VALUES' )",
306 NULL, NULL },
307 { "suffixmassage", "virtual> <real", 2, 3, 0,
308 ARG_MAGIC|LDAP_BACK_CFG_SUFFIXM,
309 meta_back_cf_gen, NULL, NULL, NULL },
310
311 { "map", "attribute|objectClass> [*|<local>] *|<remote", 3, 4, 0,
312 ARG_MAGIC|LDAP_BACK_CFG_MAP,
313 meta_back_cf_gen, "( OLcfgDbAt:3.102 "
314 "NAME 'olcDbMap' "
315 "DESC 'Map attribute and objectclass names' "
316 "EQUALITY caseIgnoreMatch "
317 "SYNTAX OMsDirectoryString "
318 "X-ORDERED 'VALUES' )",
319 NULL, NULL },
320
321 { "subtree-exclude", "pattern", 2, 2, 0,
322 ARG_MAGIC|LDAP_BACK_CFG_SUBTREE_EX,
323 meta_back_cf_gen, "( OLcfgDbAt:3.103 "
324 "NAME 'olcDbSubtreeExclude' "
325 "DESC 'DN of subtree to exclude from target' "
326 "EQUALITY caseIgnoreMatch "
327 "SYNTAX OMsDirectoryString )",
328 NULL, NULL },
329 { "subtree-include", "pattern", 2, 2, 0,
330 ARG_MAGIC|LDAP_BACK_CFG_SUBTREE_IN,
331 meta_back_cf_gen, "( OLcfgDbAt:3.104 "
332 "NAME 'olcDbSubtreeInclude' "
333 "DESC 'DN of subtree to include in target' "
334 "EQUALITY caseIgnoreMatch "
335 "SYNTAX OMsDirectoryString )",
336 NULL, NULL },
337 { "default-target", "[none|<target ID>]", 1, 2, 0,
338 ARG_MAGIC|LDAP_BACK_CFG_DEFAULT_T,
339 meta_back_cf_gen, "( OLcfgDbAt:3.105 "
340 "NAME 'olcDbDefaultTarget' "
341 "DESC 'Specify the default target' "
342 "EQUALITY caseIgnoreMatch "
343 "SYNTAX OMsDirectoryString "
344 "SINGLE-VALUE )",
345 NULL, NULL },
346 { "dncache-ttl", "ttl", 2, 2, 0,
347 ARG_MAGIC|LDAP_BACK_CFG_DNCACHE_TTL,
348 meta_back_cf_gen, "( OLcfgDbAt:3.106 "
349 "NAME 'olcDbDnCacheTtl' "
350 "DESC 'dncache ttl' "
351 "EQUALITY caseIgnoreMatch "
352 "SYNTAX OMsDirectoryString "
353 "SINGLE-VALUE )",
354 NULL, NULL },
355 { "bind-timeout", "microseconds", 2, 2, 0,
356 ARG_MAGIC|ARG_ULONG|LDAP_BACK_CFG_BIND_TIMEOUT,
357 meta_back_cf_gen, "( OLcfgDbAt:3.107 "
358 "NAME 'olcDbBindTimeout' "
359 "DESC 'bind timeout' "
360 "EQUALITY integerMatch "
361 "SYNTAX OMsInteger "
362 "SINGLE-VALUE )",
363 NULL, NULL },
364 { "onerr", "CONTINUE|report|stop", 2, 2, 0,
365 ARG_MAGIC|LDAP_BACK_CFG_ONERR,
366 meta_back_cf_gen, "( OLcfgDbAt:3.108 "
367 "NAME 'olcDbOnErr' "
368 "DESC 'error handling' "
369 "EQUALITY caseIgnoreMatch "
370 "SYNTAX OMsDirectoryString "
371 "SINGLE-VALUE )",
372 NULL, NULL },
373 { "pseudoroot-bind-defer", "TRUE|false", 2, 2, 0,
374 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER,
375 meta_back_cf_gen, "( OLcfgDbAt:3.109 "
376 "NAME 'olcDbPseudoRootBindDefer' "
377 "DESC 'error handling' "
378 "EQUALITY booleanMatch "
379 "SYNTAX OMsBoolean "
380 "SINGLE-VALUE )",
381 NULL, NULL },
382 { "root-bind-defer", "TRUE|false", 2, 2, 0,
383 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER,
384 meta_back_cf_gen, NULL, NULL, NULL },
385 { "pseudorootdn", "dn", 2, 2, 0,
386 ARG_MAGIC|ARG_DN|ARG_QUOTE|LDAP_BACK_CFG_PSEUDOROOTDN,
387 meta_back_cf_gen, NULL, NULL, NULL },
388 { "pseudorootpw", "password", 2, 2, 0,
389 ARG_MAGIC|ARG_STRING|LDAP_BACK_CFG_PSEUDOROOTPW,
390 meta_back_cf_gen, NULL, NULL, NULL },
391 { "nretries", "NEVER|forever|<number>", 2, 2, 0,
392 ARG_MAGIC|LDAP_BACK_CFG_NRETRIES,
393 meta_back_cf_gen, "( OLcfgDbAt:3.110 "
394 "NAME 'olcDbNretries' "
395 "DESC 'retry handling' "
396 "EQUALITY caseIgnoreMatch "
397 "SYNTAX OMsDirectoryString "
398 "SINGLE-VALUE )",
399 NULL, NULL },
400 { "client-pr", "accept-unsolicited|disable|<size>", 2, 2, 0,
401 ARG_MAGIC|LDAP_BACK_CFG_CLIENT_PR,
402 meta_back_cf_gen, "( OLcfgDbAt:3.111 "
403 "NAME 'olcDbClientPr' "
404 "DESC 'PagedResults handling' "
405 "EQUALITY caseIgnoreMatch "
406 "SYNTAX OMsDirectoryString "
407 "SINGLE-VALUE )",
408 NULL, NULL },
409
410 { "", "", 0, 0, 0, ARG_IGNORED,
411 NULL, "( OLcfgDbAt:3.100 NAME 'olcMetaSub' "
412 "DESC 'Placeholder to name a Target entry' "
413 "EQUALITY caseIgnoreMatch "
414 "SYNTAX OMsDirectoryString "
415 "SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL },
416
417 { "keepalive", "keepalive", 2, 2, 0,
418 ARG_MAGIC|LDAP_BACK_CFG_KEEPALIVE,
419 meta_back_cf_gen, "( OLcfgDbAt:3.29 "
420 "NAME 'olcDbKeepalive' "
421 "DESC 'TCP keepalive' "
422 "EQUALITY caseIgnoreMatch "
423 "SYNTAX OMsDirectoryString "
424 "SINGLE-VALUE )",
425 NULL, NULL },
426
427 { "tcp-user-timeout", "milliseconds", 2, 2, 0,
428 ARG_MAGIC|ARG_UINT|LDAP_BACK_CFG_TCP_USER_TIMEOUT,
429 meta_back_cf_gen, "( OLcfgDbAt:3.30 "
430 "NAME 'olcDbTcpUserTimeout' "
431 "DESC 'TCP User Timeout' "
432 "SYNTAX OMsInteger "
433 "SINGLE-VALUE )",
434 NULL, NULL },
435
436 { "filter", "pattern", 2, 2, 0,
437 ARG_MAGIC|LDAP_BACK_CFG_FILTER,
438 meta_back_cf_gen, "( OLcfgDbAt:3.112 "
439 "NAME 'olcDbFilter' "
440 "DESC 'Filter regex pattern to include in target' "
441 "EQUALITY caseExactMatch "
442 "SYNTAX OMsDirectoryString )",
443 NULL, NULL },
444
445 { NULL, NULL, 0, 0, 0, ARG_IGNORED,
446 NULL, NULL, NULL, NULL }
447 };
448
449 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
450 #define ST_ATTR "$ olcDbSessionTrackingRequest "
451 #else
452 #define ST_ATTR ""
453 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
454
455 #define COMMON_ATTRS \
456 "$ olcDbBindTimeout " \
457 "$ olcDbCancel " \
458 "$ olcDbChaseReferrals " \
459 "$ olcDbClientPr " \
460 "$ olcDbDefaultTarget " \
461 "$ olcDbNetworkTimeout " \
462 "$ olcDbNoRefs " \
463 "$ olcDbNoUndefFilter " \
464 "$ olcDbNretries " \
465 "$ olcDbProtocolVersion " \
466 "$ olcDbQuarantine " \
467 "$ olcDbRebindAsUser " \
468 ST_ATTR \
469 "$ olcDbStartTLS " \
470 "$ olcDbTFSupport "
471
472 static ConfigOCs metaocs[] = {
473 { "( OLcfgDbOc:3.2 "
474 "NAME 'olcMetaConfig' "
475 "DESC 'Meta backend configuration' "
476 "SUP olcDatabaseConfig "
477 "MAY ( olcDbConnTtl "
478 "$ olcDbDnCacheTtl "
479 "$ olcDbIdleTimeout "
480 "$ olcDbOnErr "
481 "$ olcDbPseudoRootBindDefer "
482 "$ olcDbSingleConn "
483 "$ olcDbUseTemporaryConn "
484 "$ olcDbConnectionPoolMax "
485
486 /* defaults, may be overridden per-target */
487 COMMON_ATTRS
488 ") )",
489 Cft_Database, metacfg, NULL, meta_cfadd },
490 { "( OLcfgDbOc:3.3 "
491 "NAME 'olcMetaTargetConfig' "
492 "DESC 'Meta target configuration' "
493 "SUP olcConfig STRUCTURAL "
494 "MUST ( olcMetaSub $ olcDbURI ) "
495 "MAY ( olcDbIDAssertAuthzFrom "
496 "$ olcDbIDAssertBind "
497 "$ olcDbMap "
498 "$ olcDbRewrite "
499 "$ olcDbSubtreeExclude "
500 "$ olcDbSubtreeInclude "
501 "$ olcDbTimeout "
502 "$ olcDbKeepalive "
503 "$ olcDbTcpUserTimeout "
504 "$ olcDbFilter "
505
506 /* defaults may be inherited */
507 COMMON_ATTRS
508 ") )",
509 Cft_Misc, metacfg, meta_ldadd },
510 { NULL, 0, NULL }
511 };
512
513 static int
meta_ldadd(CfEntryInfo * p,Entry * e,ConfigArgs * c)514 meta_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *c )
515 {
516 if ( p->ce_type != Cft_Database || !p->ce_be ||
517 p->ce_be->be_cf_ocs != metaocs )
518 return LDAP_CONSTRAINT_VIOLATION;
519
520 c->be = p->ce_be;
521 return LDAP_SUCCESS;
522 }
523
524 static int
meta_cfadd(Operation * op,SlapReply * rs,Entry * p,ConfigArgs * c)525 meta_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *c )
526 {
527 metainfo_t *mi = ( metainfo_t * )c->be->be_private;
528 struct berval bv;
529 int i;
530
531 bv.bv_val = c->cr_msg;
532 for ( i=0; i<mi->mi_ntargets; i++ ) {
533 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg),
534 "olcMetaSub=" SLAP_X_ORDERED_FMT "uri", i );
535 c->ca_private = mi->mi_targets[i];
536 c->valx = i;
537 config_build_entry( op, rs, p->e_private, c,
538 &bv, &metaocs[1], NULL );
539 }
540
541 return LDAP_SUCCESS;
542 }
543
544 static int
meta_rwi_init(struct rewrite_info ** rwm_rw)545 meta_rwi_init( struct rewrite_info **rwm_rw )
546 {
547 char *rargv[ 3 ];
548
549 *rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
550 if ( *rwm_rw == NULL ) {
551 return -1;
552 }
553 /*
554 * the filter rewrite as a string must be disabled
555 * by default; it can be re-enabled by adding rules;
556 * this creates an empty rewriteContext
557 */
558 rargv[ 0 ] = "rewriteContext";
559 rargv[ 1 ] = "searchFilter";
560 rargv[ 2 ] = NULL;
561 rewrite_parse( *rwm_rw, "<suffix massage>", 1, 2, rargv );
562
563 rargv[ 0 ] = "rewriteContext";
564 rargv[ 1 ] = "default";
565 rargv[ 2 ] = NULL;
566 rewrite_parse( *rwm_rw, "<suffix massage>", 1, 2, rargv );
567
568 return 0;
569 }
570
571 static int
meta_back_new_target(metatarget_t ** mtp)572 meta_back_new_target(
573 metatarget_t **mtp )
574 {
575 metatarget_t *mt;
576
577 *mtp = NULL;
578
579 mt = ch_calloc( sizeof( metatarget_t ), 1 );
580
581 if ( meta_rwi_init( &mt->mt_rwmap.rwm_rw )) {
582 ch_free( mt );
583 return -1;
584 }
585
586 ldap_pvt_thread_mutex_init( &mt->mt_uri_mutex );
587
588 mt->mt_idassert_mode = LDAP_BACK_IDASSERT_LEGACY;
589 mt->mt_idassert_authmethod = LDAP_AUTH_NONE;
590 mt->mt_idassert_tls = SB_TLS_DEFAULT;
591
592 /* by default, use proxyAuthz control on each operation */
593 mt->mt_idassert_flags = LDAP_BACK_AUTH_PRESCRIPTIVE;
594
595 *mtp = mt;
596
597 return 0;
598 }
599
600 /* Validation for suffixmassage_config */
601 static int
meta_suffixm_config(ConfigArgs * c,int argc,char ** argv,metatarget_t * mt)602 meta_suffixm_config(
603 ConfigArgs *c,
604 int argc,
605 char **argv,
606 metatarget_t *mt
607 )
608 {
609 BackendDB *tmp_bd;
610 struct berval dn, nvnc, pvnc, nrnc, prnc;
611 int j, rc;
612
613 /*
614 * syntax:
615 *
616 * suffixmassage <suffix> <massaged suffix>
617 *
618 * the <suffix> field must be defined as a valid suffix
619 * (or suffixAlias?) for the current database;
620 * the <massaged suffix> shouldn't have already been
621 * defined as a valid suffix or suffixAlias for the
622 * current server
623 */
624
625 ber_str2bv( argv[ 1 ], 0, 0, &dn );
626 if ( dnPrettyNormal( NULL, &dn, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
627 snprintf( c->cr_msg, sizeof( c->cr_msg ),
628 "suffix \"%s\" is invalid",
629 argv[1] );
630 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
631 return 1;
632 }
633
634 for ( j = 0; !BER_BVISNULL( &c->be->be_nsuffix[ j ] ); j++ ) {
635 if ( dnIsSuffix( &nvnc, &c->be->be_nsuffix[ 0 ] ) ) {
636 break;
637 }
638 }
639
640 if ( BER_BVISNULL( &c->be->be_nsuffix[ j ] ) ) {
641 snprintf( c->cr_msg, sizeof( c->cr_msg ),
642 "suffix \"%s\" must be within the database naming context",
643 argv[1] );
644 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
645 free( pvnc.bv_val );
646 free( nvnc.bv_val );
647 return 1;
648 }
649
650 ber_str2bv( argv[ 2 ], 0, 0, &dn );
651 if ( dnPrettyNormal( NULL, &dn, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
652 snprintf( c->cr_msg, sizeof( c->cr_msg ),
653 "massaged suffix \"%s\" is invalid",
654 argv[2] );
655 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
656 free( pvnc.bv_val );
657 free( nvnc.bv_val );
658 return 1;
659 }
660
661 tmp_bd = select_backend( &nrnc, 0 );
662 if ( tmp_bd != NULL && tmp_bd->be_private == c->be->be_private ) {
663 Debug( LDAP_DEBUG_ANY,
664 "%s: warning: <massaged suffix> \"%s\" resolves to this database, in "
665 "\"suffixMassage <suffix> <massaged suffix>\"\n",
666 c->log, prnc.bv_val );
667 }
668
669 /*
670 * The suffix massaging is emulated by means of the
671 * rewrite capabilities
672 */
673 rc = suffix_massage_config( mt->mt_rwmap.rwm_rw,
674 &pvnc, &nvnc, &prnc, &nrnc );
675
676 free( pvnc.bv_val );
677 free( nvnc.bv_val );
678 free( prnc.bv_val );
679 free( nrnc.bv_val );
680
681 return rc;
682 }
683
684 int
meta_subtree_free(metasubtree_t * ms)685 meta_subtree_free( metasubtree_t *ms )
686 {
687 switch ( ms->ms_type ) {
688 case META_ST_SUBTREE:
689 case META_ST_SUBORDINATE:
690 ber_memfree( ms->ms_dn.bv_val );
691 break;
692
693 case META_ST_REGEX:
694 regfree( &ms->ms_regex );
695 ber_memfree( ms->ms_regex_pattern.bv_val );
696 break;
697
698 default:
699 return -1;
700 }
701
702 ch_free( ms );
703 return 0;
704 }
705
706 int
meta_subtree_destroy(metasubtree_t * ms)707 meta_subtree_destroy( metasubtree_t *ms )
708 {
709 if ( ms->ms_next ) {
710 meta_subtree_destroy( ms->ms_next );
711 }
712
713 return meta_subtree_free( ms );
714 }
715
716 static void
meta_filter_free(metafilter_t * mf)717 meta_filter_free( metafilter_t *mf )
718 {
719 regfree( &mf->mf_regex );
720 ber_memfree( mf->mf_regex_pattern.bv_val );
721 ch_free( mf );
722 }
723
724 void
meta_filter_destroy(metafilter_t * mf)725 meta_filter_destroy( metafilter_t *mf )
726 {
727 if ( mf->mf_next )
728 meta_filter_destroy( mf->mf_next );
729 meta_filter_free( mf );
730 }
731
732 static struct berval st_styles[] = {
733 BER_BVC("subtree"),
734 BER_BVC("children"),
735 BER_BVC("regex")
736 };
737
738 static int
meta_subtree_unparse(ConfigArgs * c,metatarget_t * mt)739 meta_subtree_unparse(
740 ConfigArgs *c,
741 metatarget_t *mt )
742 {
743 metasubtree_t *ms;
744 struct berval bv, *style;
745
746 if ( !mt->mt_subtree )
747 return 1;
748
749 /* can only be one of exclude or include */
750 if (( c->type == LDAP_BACK_CFG_SUBTREE_EX ) ^ mt->mt_subtree_exclude )
751 return 1;
752
753 bv.bv_val = c->cr_msg;
754 for ( ms=mt->mt_subtree; ms; ms=ms->ms_next ) {
755 if (ms->ms_type == META_ST_SUBTREE)
756 style = &st_styles[0];
757 else if ( ms->ms_type == META_ST_SUBORDINATE )
758 style = &st_styles[1];
759 else if ( ms->ms_type == META_ST_REGEX )
760 style = &st_styles[2];
761 else {
762 assert(0);
763 continue;
764 }
765 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg),
766 "dn.%s:%s", style->bv_val, ms->ms_dn.bv_val );
767 value_add_one( &c->rvalue_vals, &bv );
768 }
769 return 0;
770 }
771
772 static int
meta_subtree_config(metatarget_t * mt,ConfigArgs * c)773 meta_subtree_config(
774 metatarget_t *mt,
775 ConfigArgs *c )
776 {
777 meta_st_t type = META_ST_SUBTREE;
778 char *pattern;
779 struct berval ndn = BER_BVNULL;
780 metasubtree_t *ms = NULL;
781
782 if ( c->type == LDAP_BACK_CFG_SUBTREE_EX ) {
783 if ( mt->mt_subtree && !mt->mt_subtree_exclude ) {
784 snprintf( c->cr_msg, sizeof(c->cr_msg),
785 "\"subtree-exclude\" incompatible with previous \"subtree-include\" directives" );
786 return 1;
787 }
788
789 mt->mt_subtree_exclude = 1;
790
791 } else {
792 if ( mt->mt_subtree && mt->mt_subtree_exclude ) {
793 snprintf( c->cr_msg, sizeof(c->cr_msg),
794 "\"subtree-include\" incompatible with previous \"subtree-exclude\" directives" );
795 return 1;
796 }
797 }
798
799 pattern = c->argv[1];
800 if ( strncasecmp( pattern, "dn", STRLENOF( "dn" ) ) == 0 ) {
801 char *style;
802
803 pattern = &pattern[STRLENOF( "dn")];
804
805 if ( pattern[0] == '.' ) {
806 style = &pattern[1];
807
808 if ( strncasecmp( style, "subtree", STRLENOF( "subtree" ) ) == 0 ) {
809 type = META_ST_SUBTREE;
810 pattern = &style[STRLENOF( "subtree" )];
811
812 } else if ( strncasecmp( style, "children", STRLENOF( "children" ) ) == 0 ) {
813 type = META_ST_SUBORDINATE;
814 pattern = &style[STRLENOF( "children" )];
815
816 } else if ( strncasecmp( style, "sub", STRLENOF( "sub" ) ) == 0 ) {
817 type = META_ST_SUBTREE;
818 pattern = &style[STRLENOF( "sub" )];
819
820 } else if ( strncasecmp( style, "regex", STRLENOF( "regex" ) ) == 0 ) {
821 type = META_ST_REGEX;
822 pattern = &style[STRLENOF( "regex" )];
823
824 } else {
825 snprintf( c->cr_msg, sizeof(c->cr_msg), "unknown style in \"dn.<style>\"" );
826 return 1;
827 }
828 }
829
830 if ( pattern[0] != ':' ) {
831 snprintf( c->cr_msg, sizeof(c->cr_msg), "missing colon after \"dn.<style>\"" );
832 return 1;
833 }
834 pattern++;
835 }
836
837 switch ( type ) {
838 case META_ST_SUBTREE:
839 case META_ST_SUBORDINATE: {
840 struct berval dn;
841
842 ber_str2bv( pattern, 0, 0, &dn );
843 if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL )
844 != LDAP_SUCCESS )
845 {
846 snprintf( c->cr_msg, sizeof(c->cr_msg), "DN=\"%s\" is invalid", pattern );
847 return 1;
848 }
849
850 if ( !dnIsSuffix( &ndn, &mt->mt_nsuffix ) ) {
851 snprintf( c->cr_msg, sizeof(c->cr_msg),
852 "DN=\"%s\" is not a subtree of target \"%s\"",
853 pattern, mt->mt_nsuffix.bv_val );
854 ber_memfree( ndn.bv_val );
855 return( 1 );
856 }
857 } break;
858
859 default:
860 /* silence warnings */
861 break;
862 }
863
864 ms = ch_calloc( sizeof( metasubtree_t ), 1 );
865 ms->ms_type = type;
866
867 switch ( ms->ms_type ) {
868 case META_ST_SUBTREE:
869 case META_ST_SUBORDINATE:
870 ms->ms_dn = ndn;
871 break;
872
873 case META_ST_REGEX: {
874 int rc;
875
876 rc = regcomp( &ms->ms_regex, pattern, REG_EXTENDED|REG_ICASE );
877 if ( rc != 0 ) {
878 char regerr[ SLAP_TEXT_BUFLEN ];
879
880 regerror( rc, &ms->ms_regex, regerr, sizeof(regerr) );
881
882 snprintf( c->cr_msg, sizeof( c->cr_msg ),
883 "regular expression \"%s\" bad because of %s",
884 pattern, regerr );
885 ch_free( ms );
886 return 1;
887 }
888 ber_str2bv( pattern, 0, 1, &ms->ms_regex_pattern );
889 } break;
890 }
891
892 if ( mt->mt_subtree == NULL ) {
893 mt->mt_subtree = ms;
894
895 } else {
896 metasubtree_t **msp;
897
898 for ( msp = &mt->mt_subtree; *msp; ) {
899 switch ( ms->ms_type ) {
900 case META_ST_SUBTREE:
901 switch ( (*msp)->ms_type ) {
902 case META_ST_SUBTREE:
903 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
904 metasubtree_t *tmp = *msp;
905 Debug( LDAP_DEBUG_CONFIG,
906 "%s: previous rule \"dn.subtree:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n",
907 c->log, pattern, (*msp)->ms_dn.bv_val );
908 *msp = (*msp)->ms_next;
909 tmp->ms_next = NULL;
910 meta_subtree_destroy( tmp );
911 continue;
912
913 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) ) {
914 Debug( LDAP_DEBUG_CONFIG,
915 "%s: previous rule \"dn.subtree:%s\" contains rule \"dn.subtree:%s\" (ignored)\n",
916 c->log, (*msp)->ms_dn.bv_val, pattern );
917 meta_subtree_destroy( ms );
918 ms = NULL;
919 return( 0 );
920 }
921 break;
922
923 case META_ST_SUBORDINATE:
924 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
925 metasubtree_t *tmp = *msp;
926 Debug( LDAP_DEBUG_CONFIG,
927 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n",
928 c->log, pattern, (*msp)->ms_dn.bv_val );
929 *msp = (*msp)->ms_next;
930 tmp->ms_next = NULL;
931 meta_subtree_destroy( tmp );
932 continue;
933
934 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) && ms->ms_dn.bv_len > (*msp)->ms_dn.bv_len ) {
935 Debug( LDAP_DEBUG_CONFIG,
936 "%s: previous rule \"dn.children:%s\" contains rule \"dn.subtree:%s\" (ignored)\n",
937 c->log, (*msp)->ms_dn.bv_val, pattern );
938 meta_subtree_destroy( ms );
939 ms = NULL;
940 return( 0 );
941 }
942 break;
943
944 case META_ST_REGEX:
945 if ( regexec( &(*msp)->ms_regex, ms->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) {
946 Debug( LDAP_DEBUG_CONFIG,
947 "%s: previous rule \"dn.regex:%s\" may contain rule \"dn.subtree:%s\"\n",
948 c->log, (*msp)->ms_regex_pattern.bv_val, ms->ms_dn.bv_val );
949 }
950 break;
951 }
952 break;
953
954 case META_ST_SUBORDINATE:
955 switch ( (*msp)->ms_type ) {
956 case META_ST_SUBTREE:
957 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
958 metasubtree_t *tmp = *msp;
959 Debug( LDAP_DEBUG_CONFIG,
960 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n",
961 c->log, pattern, (*msp)->ms_dn.bv_val );
962 *msp = (*msp)->ms_next;
963 tmp->ms_next = NULL;
964 meta_subtree_destroy( tmp );
965 continue;
966
967 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) && ms->ms_dn.bv_len > (*msp)->ms_dn.bv_len ) {
968 Debug( LDAP_DEBUG_CONFIG,
969 "%s: previous rule \"dn.children:%s\" contains rule \"dn.subtree:%s\" (ignored)\n",
970 c->log, (*msp)->ms_dn.bv_val, pattern );
971 meta_subtree_destroy( ms );
972 ms = NULL;
973 return( 0 );
974 }
975 break;
976
977 case META_ST_SUBORDINATE:
978 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
979 metasubtree_t *tmp = *msp;
980 Debug( LDAP_DEBUG_CONFIG,
981 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.children:%s\" (replaced)\n",
982 c->log, pattern, (*msp)->ms_dn.bv_val );
983 *msp = (*msp)->ms_next;
984 tmp->ms_next = NULL;
985 meta_subtree_destroy( tmp );
986 continue;
987
988 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) ) {
989 Debug( LDAP_DEBUG_CONFIG,
990 "%s: previous rule \"dn.children:%s\" contains rule \"dn.children:%s\" (ignored)\n",
991 c->log, (*msp)->ms_dn.bv_val, pattern );
992 meta_subtree_destroy( ms );
993 ms = NULL;
994 return( 0 );
995 }
996 break;
997
998 case META_ST_REGEX:
999 if ( regexec( &(*msp)->ms_regex, ms->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) {
1000 Debug( LDAP_DEBUG_CONFIG,
1001 "%s: previous rule \"dn.regex:%s\" may contain rule \"dn.subtree:%s\"\n",
1002 c->log, (*msp)->ms_regex_pattern.bv_val, ms->ms_dn.bv_val );
1003 }
1004 break;
1005 }
1006 break;
1007
1008 case META_ST_REGEX:
1009 switch ( (*msp)->ms_type ) {
1010 case META_ST_SUBTREE:
1011 case META_ST_SUBORDINATE:
1012 if ( regexec( &ms->ms_regex, (*msp)->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) {
1013 Debug( LDAP_DEBUG_CONFIG,
1014 "%s: previous rule \"dn.subtree:%s\" may be contained in rule \"dn.regex:%s\"\n",
1015 c->log, (*msp)->ms_dn.bv_val, ms->ms_regex_pattern.bv_val );
1016 }
1017 break;
1018
1019 case META_ST_REGEX:
1020 /* no check possible */
1021 break;
1022 }
1023 break;
1024 }
1025
1026 msp = &(*msp)->ms_next;
1027 }
1028
1029 *msp = ms;
1030 }
1031
1032 return 0;
1033 }
1034
1035 static slap_verbmasks idassert_mode[] = {
1036 { BER_BVC("self"), LDAP_BACK_IDASSERT_SELF },
1037 { BER_BVC("anonymous"), LDAP_BACK_IDASSERT_ANONYMOUS },
1038 { BER_BVC("none"), LDAP_BACK_IDASSERT_NOASSERT },
1039 { BER_BVC("legacy"), LDAP_BACK_IDASSERT_LEGACY },
1040 { BER_BVNULL, 0 }
1041 };
1042
1043 static slap_verbmasks tls_mode[] = {
1044 { BER_BVC( "propagate" ), LDAP_BACK_F_TLS_PROPAGATE_MASK },
1045 { BER_BVC( "try-propagate" ), LDAP_BACK_F_PROPAGATE_TLS },
1046 { BER_BVC( "start" ), LDAP_BACK_F_TLS_USE_MASK },
1047 { BER_BVC( "try-start" ), LDAP_BACK_F_USE_TLS },
1048 { BER_BVC( "ldaps" ), LDAP_BACK_F_TLS_LDAPS },
1049 { BER_BVC( "none" ), LDAP_BACK_F_NONE },
1050 { BER_BVNULL, 0 }
1051 };
1052
1053 static slap_verbmasks t_f_mode[] = {
1054 { BER_BVC( "yes" ), LDAP_BACK_F_T_F },
1055 { BER_BVC( "discover" ), LDAP_BACK_F_T_F_DISCOVER },
1056 { BER_BVC( "no" ), LDAP_BACK_F_NONE },
1057 { BER_BVNULL, 0 }
1058 };
1059
1060 static slap_verbmasks cancel_mode[] = {
1061 { BER_BVC( "ignore" ), LDAP_BACK_F_CANCEL_IGNORE },
1062 { BER_BVC( "exop" ), LDAP_BACK_F_CANCEL_EXOP },
1063 { BER_BVC( "exop-discover" ), LDAP_BACK_F_CANCEL_EXOP_DISCOVER },
1064 { BER_BVC( "abandon" ), LDAP_BACK_F_CANCEL_ABANDON },
1065 { BER_BVNULL, 0 }
1066 };
1067
1068 static slap_verbmasks onerr_mode[] = {
1069 { BER_BVC( "stop" ), META_BACK_F_ONERR_STOP },
1070 { BER_BVC( "report" ), META_BACK_F_ONERR_REPORT },
1071 { BER_BVC( "continue" ), LDAP_BACK_F_NONE },
1072 { BER_BVNULL, 0 }
1073 };
1074
1075 /* see enum in slap.h */
1076 static slap_cf_aux_table timeout_table[] = {
1077 { BER_BVC("bind="), SLAP_OP_BIND * sizeof( time_t ), 'u', 0, NULL },
1078 /* unbind makes no sense */
1079 { BER_BVC("add="), SLAP_OP_ADD * sizeof( time_t ), 'u', 0, NULL },
1080 { BER_BVC("delete="), SLAP_OP_DELETE * sizeof( time_t ), 'u', 0, NULL },
1081 { BER_BVC("modrdn="), SLAP_OP_MODRDN * sizeof( time_t ), 'u', 0, NULL },
1082 { BER_BVC("modify="), SLAP_OP_MODIFY * sizeof( time_t ), 'u', 0, NULL },
1083 { BER_BVC("compare="), SLAP_OP_COMPARE * sizeof( time_t ), 'u', 0, NULL },
1084 { BER_BVC("search="), SLAP_OP_SEARCH * sizeof( time_t ), 'u', 0, NULL },
1085 /* abandon makes little sense */
1086 #if 0 /* not implemented yet */
1087 { BER_BVC("extended="), SLAP_OP_EXTENDED * sizeof( time_t ), 'u', 0, NULL },
1088 #endif
1089 { BER_BVNULL, 0, 0, 0, NULL }
1090 };
1091
1092 static int
meta_cf_cleanup(ConfigArgs * c)1093 meta_cf_cleanup( ConfigArgs *c )
1094 {
1095 metainfo_t *mi = ( metainfo_t * )c->be->be_private;
1096 metatarget_t *mt = c->ca_private;
1097
1098 return meta_target_finish( mi, mt, c->log, c->cr_msg, sizeof( c->cr_msg ));
1099 }
1100
1101 static int
meta_back_cf_gen(ConfigArgs * c)1102 meta_back_cf_gen( ConfigArgs *c )
1103 {
1104 metainfo_t *mi = ( metainfo_t * )c->be->be_private;
1105 metatarget_t *mt;
1106 metacommon_t *mc;
1107
1108 int i, rc = 0;
1109
1110 assert( mi != NULL );
1111
1112 if ( c->op == SLAP_CONFIG_EMIT || c->op == LDAP_MOD_DELETE ) {
1113 if ( !mi )
1114 return 1;
1115
1116 if ( c->table == Cft_Database ) {
1117 mt = NULL;
1118 mc = &mi->mi_mc;
1119 } else {
1120 mt = c->ca_private;
1121 mc = &mt->mt_mc;
1122 }
1123 }
1124
1125 if ( c->op == SLAP_CONFIG_EMIT ) {
1126 struct berval bv = BER_BVNULL;
1127
1128 switch( c->type ) {
1129 /* Base attrs */
1130 case LDAP_BACK_CFG_CONN_TTL:
1131 if ( mi->mi_conn_ttl == 0 ) {
1132 return 1;
1133 } else {
1134 char buf[ SLAP_TEXT_BUFLEN ];
1135
1136 lutil_unparse_time( buf, sizeof( buf ), mi->mi_conn_ttl );
1137 ber_str2bv( buf, 0, 0, &bv );
1138 value_add_one( &c->rvalue_vals, &bv );
1139 }
1140 break;
1141
1142 case LDAP_BACK_CFG_DNCACHE_TTL:
1143 if ( mi->mi_cache.ttl == META_DNCACHE_DISABLED ) {
1144 return 1;
1145 } else if ( mi->mi_cache.ttl == META_DNCACHE_FOREVER ) {
1146 BER_BVSTR( &bv, "forever" );
1147 } else {
1148 char buf[ SLAP_TEXT_BUFLEN ];
1149
1150 lutil_unparse_time( buf, sizeof( buf ), mi->mi_cache.ttl );
1151 ber_str2bv( buf, 0, 0, &bv );
1152 }
1153 value_add_one( &c->rvalue_vals, &bv );
1154 break;
1155
1156 case LDAP_BACK_CFG_IDLE_TIMEOUT:
1157 if ( mi->mi_idle_timeout == 0 ) {
1158 return 1;
1159 } else {
1160 char buf[ SLAP_TEXT_BUFLEN ];
1161
1162 lutil_unparse_time( buf, sizeof( buf ), mi->mi_idle_timeout );
1163 ber_str2bv( buf, 0, 0, &bv );
1164 value_add_one( &c->rvalue_vals, &bv );
1165 }
1166 break;
1167
1168 case LDAP_BACK_CFG_ONERR:
1169 enum_to_verb( onerr_mode, mi->mi_flags & META_BACK_F_ONERR_MASK, &bv );
1170 if ( BER_BVISNULL( &bv )) {
1171 rc = 1;
1172 } else {
1173 value_add_one( &c->rvalue_vals, &bv );
1174 }
1175 break;
1176
1177 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER:
1178 c->value_int = META_BACK_DEFER_ROOTDN_BIND( mi );
1179 break;
1180
1181 case LDAP_BACK_CFG_SINGLECONN:
1182 c->value_int = LDAP_BACK_SINGLECONN( mi );
1183 break;
1184
1185 case LDAP_BACK_CFG_USETEMP:
1186 c->value_int = LDAP_BACK_USE_TEMPORARIES( mi );
1187 break;
1188
1189 case LDAP_BACK_CFG_CONNPOOLMAX:
1190 c->value_int = mi->mi_conn_priv_max;
1191 break;
1192
1193 /* common attrs */
1194 case LDAP_BACK_CFG_BIND_TIMEOUT:
1195 if ( mc->mc_bind_timeout.tv_sec == 0 &&
1196 mc->mc_bind_timeout.tv_usec == 0 ) {
1197 return 1;
1198 } else {
1199 c->value_ulong = mc->mc_bind_timeout.tv_sec * 1000000UL +
1200 mc->mc_bind_timeout.tv_usec;
1201 }
1202 break;
1203
1204 case LDAP_BACK_CFG_CANCEL: {
1205 slap_mask_t mask = LDAP_BACK_F_CANCEL_MASK2;
1206
1207 if ( mt && META_BACK_TGT_CANCEL_DISCOVER( mt ) ) {
1208 mask &= ~LDAP_BACK_F_CANCEL_EXOP;
1209 }
1210 enum_to_verb( cancel_mode, (mc->mc_flags & mask), &bv );
1211 if ( BER_BVISNULL( &bv ) ) {
1212 /* there's something wrong... */
1213 assert( 0 );
1214 rc = 1;
1215
1216 } else {
1217 value_add_one( &c->rvalue_vals, &bv );
1218 }
1219 } break;
1220
1221 case LDAP_BACK_CFG_CHASE:
1222 c->value_int = META_BACK_CMN_CHASE_REFERRALS(mc);
1223 break;
1224
1225 #ifdef SLAPD_META_CLIENT_PR
1226 case LDAP_BACK_CFG_CLIENT_PR:
1227 if ( mc->mc_ps == META_CLIENT_PR_DISABLE ) {
1228 return 1;
1229 } else if ( mc->mc_ps == META_CLIENT_PR_ACCEPT_UNSOLICITED ) {
1230 BER_BVSTR( &bv, "accept-unsolicited" );
1231 } else {
1232 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d", mc->mc_ps );
1233 bv.bv_val = c->cr_msg;
1234 }
1235 value_add_one( &c->rvalue_vals, &bv );
1236 break;
1237 #endif /* SLAPD_META_CLIENT_PR */
1238
1239 case LDAP_BACK_CFG_DEFAULT_T:
1240 if ( mt || mi->mi_defaulttarget == META_DEFAULT_TARGET_NONE )
1241 return 1;
1242 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d", mi->mi_defaulttarget );
1243 bv.bv_val = c->cr_msg;
1244 value_add_one( &c->rvalue_vals, &bv );
1245 break;
1246
1247 case LDAP_BACK_CFG_NETWORK_TIMEOUT:
1248 if ( mc->mc_network_timeout == 0 ) {
1249 return 1;
1250 } else {
1251 char buf[ SLAP_TEXT_BUFLEN ];
1252 lutil_unparse_time( buf, sizeof( buf ), mc->mc_network_timeout );
1253 ber_str2bv( buf, 0, 0, &bv );
1254 value_add_one( &c->rvalue_vals, &bv );
1255 }
1256 break;
1257
1258 case LDAP_BACK_CFG_NOREFS:
1259 c->value_int = META_BACK_CMN_NOREFS(mc);
1260 break;
1261
1262 case LDAP_BACK_CFG_NOUNDEFFILTER:
1263 c->value_int = META_BACK_CMN_NOUNDEFFILTER(mc);
1264 break;
1265
1266 case LDAP_BACK_CFG_NRETRIES:
1267 if ( mc->mc_nretries == META_RETRY_FOREVER ) {
1268 BER_BVSTR( &bv, "forever" );
1269 } else if ( mc->mc_nretries == META_RETRY_NEVER ) {
1270 BER_BVSTR( &bv, "never" );
1271 } else {
1272 bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "%d",
1273 mc->mc_nretries );
1274 bv.bv_val = c->cr_msg;
1275 }
1276 value_add_one( &c->rvalue_vals, &bv );
1277 break;
1278
1279 case LDAP_BACK_CFG_QUARANTINE:
1280 if ( !META_BACK_CMN_QUARANTINE( mc )) {
1281 rc = 1;
1282 break;
1283 }
1284 rc = mi->mi_ldap_extra->retry_info_unparse( &mc->mc_quarantine, &bv );
1285 if ( rc == 0 ) {
1286 ber_bvarray_add( &c->rvalue_vals, &bv );
1287 }
1288 break;
1289
1290 case LDAP_BACK_CFG_REBIND:
1291 c->value_int = META_BACK_CMN_SAVECRED(mc);
1292 break;
1293
1294 case LDAP_BACK_CFG_TIMEOUT:
1295 for ( i = 0; i < SLAP_OP_LAST; i++ ) {
1296 if ( mc->mc_timeout[ i ] != 0 ) {
1297 break;
1298 }
1299 }
1300
1301 if ( i == SLAP_OP_LAST ) {
1302 return 1;
1303 }
1304
1305 BER_BVZERO( &bv );
1306 slap_cf_aux_table_unparse( mc->mc_timeout, &bv, timeout_table );
1307
1308 if ( BER_BVISNULL( &bv ) ) {
1309 return 1;
1310 }
1311
1312 for ( i = 0; isspace( (unsigned char) bv.bv_val[ i ] ); i++ )
1313 /* count spaces */ ;
1314
1315 if ( i ) {
1316 bv.bv_len -= i;
1317 AC_MEMCPY( bv.bv_val, &bv.bv_val[ i ],
1318 bv.bv_len + 1 );
1319 }
1320
1321 ber_bvarray_add( &c->rvalue_vals, &bv );
1322 break;
1323
1324 case LDAP_BACK_CFG_VERSION:
1325 if ( mc->mc_version == 0 )
1326 return 1;
1327 c->value_int = mc->mc_version;
1328 break;
1329
1330 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
1331 case LDAP_BACK_CFG_ST_REQUEST:
1332 c->value_int = META_BACK_CMN_ST_REQUEST( mc );
1333 break;
1334 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
1335
1336 case LDAP_BACK_CFG_T_F:
1337 enum_to_verb( t_f_mode, (mc->mc_flags & LDAP_BACK_F_T_F_MASK2), &bv );
1338 if ( BER_BVISNULL( &bv ) ) {
1339 /* there's something wrong... */
1340 assert( 0 );
1341 rc = 1;
1342
1343 } else {
1344 value_add_one( &c->rvalue_vals, &bv );
1345 }
1346 break;
1347
1348 case LDAP_BACK_CFG_TLS: {
1349 struct berval bc = BER_BVNULL, bv2;
1350
1351 if (( mc->mc_flags & LDAP_BACK_F_TLS_MASK ) == LDAP_BACK_F_NONE ) {
1352 rc = 1;
1353 break;
1354 }
1355 enum_to_verb( tls_mode, ( mc->mc_flags & LDAP_BACK_F_TLS_MASK ), &bv );
1356 assert( !BER_BVISNULL( &bv ) );
1357
1358 if ( mt ) {
1359 bindconf_tls_unparse( &mt->mt_tls, &bc );
1360 }
1361
1362 if ( !BER_BVISEMPTY( &bc )) {
1363 bv2.bv_len = bv.bv_len + bc.bv_len + 1;
1364 bv2.bv_val = ch_malloc( bv2.bv_len + 1 );
1365 strcpy( bv2.bv_val, bv.bv_val );
1366 bv2.bv_val[bv.bv_len] = ' ';
1367 strcpy( &bv2.bv_val[bv.bv_len + 1], bc.bv_val );
1368 ber_memfree( bc.bv_val );
1369 ber_bvarray_add( &c->rvalue_vals, &bv2 );
1370 } else {
1371 value_add_one( &c->rvalue_vals, &bv );
1372 }
1373 } break;
1374
1375 /* target attrs */
1376 case LDAP_BACK_CFG_URI: {
1377 char *p2, *p1 = strchr( mt->mt_uri, ' ' );
1378 bv.bv_len = strlen( mt->mt_uri ) + 3 + mt->mt_psuffix.bv_len;
1379 bv.bv_val = ch_malloc( bv.bv_len + 1 );
1380 p2 = bv.bv_val;
1381 *p2++ = '"';
1382 if ( p1 ) {
1383 p2 = lutil_strncopy( p2, mt->mt_uri, p1 - mt->mt_uri );
1384 } else {
1385 p2 = lutil_strcopy( p2, mt->mt_uri );
1386 }
1387 *p2++ = '/';
1388 p2 = lutil_strcopy( p2, mt->mt_psuffix.bv_val );
1389 *p2++ = '"';
1390 if ( p1 ) {
1391 strcpy( p2, p1 );
1392 }
1393 ber_bvarray_add( &c->rvalue_vals, &bv );
1394 } break;
1395
1396 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
1397 BerVarray *bvp;
1398 int i;
1399 struct berval bv = BER_BVNULL;
1400 char buf[SLAP_TEXT_BUFLEN];
1401
1402 bvp = &mt->mt_idassert_authz;
1403 if ( *bvp == NULL ) {
1404 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL )
1405 {
1406 BER_BVSTR( &bv, "*" );
1407 value_add_one( &c->rvalue_vals, &bv );
1408
1409 } else {
1410 rc = 1;
1411 }
1412 break;
1413 }
1414
1415 for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ ) {
1416 char *ptr;
1417 int len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i );
1418 bv.bv_len = ((*bvp)[ i ]).bv_len + len;
1419 bv.bv_val = ch_realloc( bv.bv_val, bv.bv_len + 1 );
1420 ptr = bv.bv_val;
1421 ptr = lutil_strcopy( ptr, buf );
1422 ptr = lutil_strncopy( ptr, ((*bvp)[ i ]).bv_val, ((*bvp)[ i ]).bv_len );
1423 value_add_one( &c->rvalue_vals, &bv );
1424 }
1425 if ( bv.bv_val ) {
1426 ber_memfree( bv.bv_val );
1427 }
1428 break;
1429 }
1430
1431 case LDAP_BACK_CFG_IDASSERT_BIND: {
1432 int i;
1433 struct berval bc = BER_BVNULL;
1434 char *ptr;
1435
1436 if ( mt->mt_idassert_authmethod == LDAP_AUTH_NONE ) {
1437 return 1;
1438 } else {
1439 ber_len_t len;
1440
1441 switch ( mt->mt_idassert_mode ) {
1442 case LDAP_BACK_IDASSERT_OTHERID:
1443 case LDAP_BACK_IDASSERT_OTHERDN:
1444 break;
1445
1446 default: {
1447 struct berval mode = BER_BVNULL;
1448
1449 enum_to_verb( idassert_mode, mt->mt_idassert_mode, &mode );
1450 if ( BER_BVISNULL( &mode ) ) {
1451 /* there's something wrong... */
1452 assert( 0 );
1453 rc = 1;
1454
1455 } else {
1456 bv.bv_len = STRLENOF( "mode=" ) + mode.bv_len;
1457 bv.bv_val = ch_malloc( bv.bv_len + 1 );
1458
1459 ptr = lutil_strcopy( bv.bv_val, "mode=" );
1460 ptr = lutil_strcopy( ptr, mode.bv_val );
1461 }
1462 break;
1463 }
1464 }
1465
1466 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) {
1467 len = bv.bv_len + STRLENOF( "authz=native" );
1468
1469 if ( !BER_BVISEMPTY( &bv ) ) {
1470 len += STRLENOF( " " );
1471 }
1472
1473 bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
1474
1475 ptr = &bv.bv_val[ bv.bv_len ];
1476
1477 if ( !BER_BVISEMPTY( &bv ) ) {
1478 ptr = lutil_strcopy( ptr, " " );
1479 }
1480
1481 (void)lutil_strcopy( ptr, "authz=native" );
1482 }
1483
1484 len = bv.bv_len + STRLENOF( "flags=non-prescriptive,override,obsolete-encoding-workaround,proxy-authz-non-critical,dn-authzid" );
1485 /* flags */
1486 if ( !BER_BVISEMPTY( &bv ) ) {
1487 len += STRLENOF( " " );
1488 }
1489
1490 bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
1491
1492 ptr = &bv.bv_val[ bv.bv_len ];
1493
1494 if ( !BER_BVISEMPTY( &bv ) ) {
1495 ptr = lutil_strcopy( ptr, " " );
1496 }
1497
1498 ptr = lutil_strcopy( ptr, "flags=" );
1499
1500 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
1501 ptr = lutil_strcopy( ptr, "prescriptive" );
1502 } else {
1503 ptr = lutil_strcopy( ptr, "non-prescriptive" );
1504 }
1505
1506 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
1507 ptr = lutil_strcopy( ptr, ",override" );
1508 }
1509
1510 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {
1511 ptr = lutil_strcopy( ptr, ",obsolete-proxy-authz" );
1512
1513 } else if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {
1514 ptr = lutil_strcopy( ptr, ",obsolete-encoding-workaround" );
1515 }
1516
1517 if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PROXYAUTHZ_CRITICAL ) {
1518 ptr = lutil_strcopy( ptr, ",proxy-authz-critical" );
1519
1520 } else {
1521 ptr = lutil_strcopy( ptr, ",proxy-authz-non-critical" );
1522 }
1523
1524 #ifdef SLAP_AUTH_DN
1525 switch ( mt->mt_idassert_flags & LDAP_BACK_AUTH_DN_MASK ) {
1526 case LDAP_BACK_AUTH_DN_AUTHZID:
1527 ptr = lutil_strcopy( ptr, ",dn-authzid" );
1528 break;
1529
1530 case LDAP_BACK_AUTH_DN_WHOAMI:
1531 ptr = lutil_strcopy( ptr, ",dn-whoami" );
1532 break;
1533
1534 default:
1535 #if 0 /* implicit */
1536 ptr = lutil_strcopy( ptr, ",dn-none" );
1537 #endif
1538 break;
1539 }
1540 #endif
1541
1542 bv.bv_len = ( ptr - bv.bv_val );
1543 /* end-of-flags */
1544 }
1545
1546 bindconf_unparse( &mt->mt_idassert.si_bc, &bc );
1547
1548 if ( !BER_BVISNULL( &bv ) ) {
1549 ber_len_t len = bv.bv_len + bc.bv_len;
1550
1551 bv.bv_val = ch_realloc( bv.bv_val, len + 1 );
1552
1553 assert( bc.bv_val[ 0 ] == ' ' );
1554
1555 ptr = lutil_strcopy( &bv.bv_val[ bv.bv_len ], bc.bv_val );
1556 free( bc.bv_val );
1557 bv.bv_len = ptr - bv.bv_val;
1558
1559 } else {
1560 for ( i = 0; isspace( (unsigned char) bc.bv_val[ i ] ); i++ )
1561 /* count spaces */ ;
1562
1563 if ( i ) {
1564 bc.bv_len -= i;
1565 AC_MEMCPY( bc.bv_val, &bc.bv_val[ i ], bc.bv_len + 1 );
1566 }
1567
1568 bv = bc;
1569 }
1570
1571 ber_bvarray_add( &c->rvalue_vals, &bv );
1572
1573 break;
1574 }
1575
1576 case LDAP_BACK_CFG_SUFFIXM: /* unused */
1577 case LDAP_BACK_CFG_REWRITE:
1578 if ( mt->mt_rwmap.rwm_bva_rewrite == NULL ) {
1579 rc = 1;
1580 } else {
1581 rc = slap_bv_x_ordered_unparse( mt->mt_rwmap.rwm_bva_rewrite, &c->rvalue_vals );
1582 }
1583 break;
1584
1585 case LDAP_BACK_CFG_MAP:
1586 if ( mt->mt_rwmap.rwm_bva_map == NULL ) {
1587 rc = 1;
1588 } else {
1589 rc = slap_bv_x_ordered_unparse( mt->mt_rwmap.rwm_bva_map, &c->rvalue_vals );
1590 }
1591 break;
1592
1593 case LDAP_BACK_CFG_SUBTREE_EX:
1594 case LDAP_BACK_CFG_SUBTREE_IN:
1595 rc = meta_subtree_unparse( c, mt );
1596 break;
1597
1598 case LDAP_BACK_CFG_FILTER:
1599 if ( mt->mt_filter == NULL ) {
1600 rc = 1;
1601 } else {
1602 metafilter_t *mf;
1603 for ( mf = mt->mt_filter; mf; mf = mf->mf_next )
1604 value_add_one( &c->rvalue_vals, &mf->mf_regex_pattern );
1605 }
1606 break;
1607
1608 /* replaced by idassert */
1609 case LDAP_BACK_CFG_PSEUDOROOTDN:
1610 case LDAP_BACK_CFG_PSEUDOROOTPW:
1611 rc = 1;
1612 break;
1613
1614 case LDAP_BACK_CFG_KEEPALIVE: {
1615 struct berval bv;
1616 char buf[AC_LINE_MAX];
1617 bv.bv_len = AC_LINE_MAX;
1618 bv.bv_val = &buf[0];
1619 slap_keepalive_parse(&bv, &mt->mt_tls.sb_keepalive, 0, 0, 1);
1620 value_add_one( &c->rvalue_vals, &bv );
1621 break;
1622 }
1623
1624 case LDAP_BACK_CFG_TCP_USER_TIMEOUT:
1625 c->value_uint = mt->mt_tls.sb_tcp_user_timeout;
1626 break;
1627
1628
1629 default:
1630 rc = 1;
1631 }
1632 return rc;
1633 } else if ( c->op == LDAP_MOD_DELETE ) {
1634 switch( c->type ) {
1635 /* Base attrs */
1636 case LDAP_BACK_CFG_CONN_TTL:
1637 mi->mi_conn_ttl = 0;
1638 break;
1639
1640 case LDAP_BACK_CFG_DNCACHE_TTL:
1641 mi->mi_cache.ttl = META_DNCACHE_DISABLED;
1642 break;
1643
1644 case LDAP_BACK_CFG_IDLE_TIMEOUT:
1645 mi->mi_idle_timeout = 0;
1646 break;
1647
1648 case LDAP_BACK_CFG_ONERR:
1649 mi->mi_flags &= ~META_BACK_F_ONERR_MASK;
1650 break;
1651
1652 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER:
1653 mi->mi_flags &= ~META_BACK_F_DEFER_ROOTDN_BIND;
1654 break;
1655
1656 case LDAP_BACK_CFG_SINGLECONN:
1657 mi->mi_flags &= ~LDAP_BACK_F_SINGLECONN;
1658 break;
1659
1660 case LDAP_BACK_CFG_USETEMP:
1661 mi->mi_flags &= ~LDAP_BACK_F_USE_TEMPORARIES;
1662 break;
1663
1664 case LDAP_BACK_CFG_CONNPOOLMAX:
1665 mi->mi_conn_priv_max = LDAP_BACK_CONN_PRIV_MIN;
1666 break;
1667
1668 /* common attrs */
1669 case LDAP_BACK_CFG_BIND_TIMEOUT:
1670 mc->mc_bind_timeout.tv_sec = 0;
1671 mc->mc_bind_timeout.tv_usec = 0;
1672 break;
1673
1674 case LDAP_BACK_CFG_CANCEL:
1675 mc->mc_flags &= ~LDAP_BACK_F_CANCEL_MASK2;
1676 break;
1677
1678 case LDAP_BACK_CFG_CHASE:
1679 mc->mc_flags &= ~LDAP_BACK_F_CHASE_REFERRALS;
1680 break;
1681
1682 #ifdef SLAPD_META_CLIENT_PR
1683 case LDAP_BACK_CFG_CLIENT_PR:
1684 mc->mc_ps = META_CLIENT_PR_DISABLE;
1685 break;
1686 #endif /* SLAPD_META_CLIENT_PR */
1687
1688 case LDAP_BACK_CFG_DEFAULT_T:
1689 mi->mi_defaulttarget = META_DEFAULT_TARGET_NONE;
1690 break;
1691
1692 case LDAP_BACK_CFG_NETWORK_TIMEOUT:
1693 mc->mc_network_timeout = 0;
1694 break;
1695
1696 case LDAP_BACK_CFG_NOREFS:
1697 mc->mc_flags &= ~LDAP_BACK_F_NOREFS;
1698 break;
1699
1700 case LDAP_BACK_CFG_NOUNDEFFILTER:
1701 mc->mc_flags &= ~LDAP_BACK_F_NOUNDEFFILTER;
1702 break;
1703
1704 case LDAP_BACK_CFG_NRETRIES:
1705 mc->mc_nretries = META_RETRY_DEFAULT;
1706 break;
1707
1708 case LDAP_BACK_CFG_QUARANTINE:
1709 if ( META_BACK_CMN_QUARANTINE( mc )) {
1710 mi->mi_ldap_extra->retry_info_destroy( &mc->mc_quarantine );
1711 mc->mc_flags &= ~LDAP_BACK_F_QUARANTINE;
1712 if ( mc == &mt->mt_mc ) {
1713 ldap_pvt_thread_mutex_destroy( &mt->mt_quarantine_mutex );
1714 mt->mt_isquarantined = 0;
1715 }
1716 }
1717 break;
1718
1719 case LDAP_BACK_CFG_REBIND:
1720 mc->mc_flags &= ~LDAP_BACK_F_SAVECRED;
1721 break;
1722
1723 case LDAP_BACK_CFG_TIMEOUT:
1724 for ( i = 0; i < SLAP_OP_LAST; i++ ) {
1725 mc->mc_timeout[ i ] = 0;
1726 }
1727 break;
1728
1729 case LDAP_BACK_CFG_VERSION:
1730 mc->mc_version = 0;
1731 break;
1732
1733 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
1734 case LDAP_BACK_CFG_ST_REQUEST:
1735 mc->mc_flags &= ~LDAP_BACK_F_ST_REQUEST;
1736 break;
1737 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
1738
1739 case LDAP_BACK_CFG_T_F:
1740 mc->mc_flags &= ~LDAP_BACK_F_T_F_MASK2;
1741 break;
1742
1743 case LDAP_BACK_CFG_TLS:
1744 mc->mc_flags &= ~LDAP_BACK_F_TLS_MASK;
1745 if ( mt )
1746 bindconf_free( &mt->mt_tls );
1747 break;
1748
1749 /* target attrs */
1750 case LDAP_BACK_CFG_URI:
1751 if ( mt->mt_uri ) {
1752 ch_free( mt->mt_uri );
1753 mt->mt_uri = NULL;
1754 }
1755 /* FIXME: should have a way to close all cached
1756 * connections associated with this target.
1757 */
1758 break;
1759
1760 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
1761 BerVarray *bvp;
1762
1763 bvp = &mt->mt_idassert_authz;
1764 if ( c->valx < 0 ) {
1765 if ( *bvp != NULL ) {
1766 ber_bvarray_free( *bvp );
1767 *bvp = NULL;
1768 }
1769
1770 } else {
1771 if ( *bvp == NULL ) {
1772 rc = 1;
1773 break;
1774 }
1775
1776 for ( i = 0; !BER_BVISNULL( &((*bvp)[ i ]) ); i++ )
1777 ;
1778
1779 if ( i >= c->valx ) {
1780 rc = 1;
1781 break;
1782 }
1783 ber_memfree( ((*bvp)[ c->valx ]).bv_val );
1784 for ( i = c->valx; !BER_BVISNULL( &((*bvp)[ i + 1 ]) ); i++ ) {
1785 (*bvp)[ i ] = (*bvp)[ i + 1 ];
1786 }
1787 BER_BVZERO( &((*bvp)[ i ]) );
1788 }
1789 } break;
1790
1791 case LDAP_BACK_CFG_IDASSERT_BIND:
1792 bindconf_free( &mt->mt_idassert.si_bc );
1793 memset( &mt->mt_idassert, 0, sizeof( slap_idassert_t ) );
1794 break;
1795
1796 case LDAP_BACK_CFG_SUFFIXM: /* unused */
1797 case LDAP_BACK_CFG_REWRITE:
1798 {
1799 if ( c->valx >= 0 ) {
1800 int i;
1801
1802 for ( i = 0; !BER_BVISNULL( &mt->mt_rwmap.rwm_bva_rewrite[ i ] ); i++ );
1803
1804 if ( c->valx >= i ) {
1805 rc = 1;
1806 break;
1807 }
1808
1809 ber_memfree( mt->mt_rwmap.rwm_bva_rewrite[ c->valx ].bv_val );
1810 for ( i = c->valx; !BER_BVISNULL( &mt->mt_rwmap.rwm_bva_rewrite[ i + 1 ] ); i++ )
1811 {
1812 mt->mt_rwmap.rwm_bva_rewrite[ i ] = mt->mt_rwmap.rwm_bva_rewrite[ i + 1 ];
1813 }
1814 BER_BVZERO( &mt->mt_rwmap.rwm_bva_rewrite[ i ] );
1815
1816 rewrite_info_delete( &mt->mt_rwmap.rwm_rw );
1817 assert( mt->mt_rwmap.rwm_rw == NULL );
1818
1819 rc = meta_rwi_init( &mt->mt_rwmap.rwm_rw );
1820
1821 for ( i = 0; !BER_BVISNULL( &mt->mt_rwmap.rwm_bva_rewrite[ i ] ); i++ )
1822 {
1823 ConfigArgs ca = { 0 };
1824
1825 ca.line = mt->mt_rwmap.rwm_bva_rewrite[ i ].bv_val;
1826 init_config_argv( &ca );
1827 config_parse_ldif( &ca );
1828
1829 if ( !strcasecmp( ca.argv[0], "suffixmassage" )) {
1830 rc = meta_suffixm_config( &ca, ca.argc, ca.argv, mt );
1831 } else {
1832 rc = rewrite_parse( mt->mt_rwmap.rwm_rw,
1833 c->fname, c->lineno, ca.argc, ca.argv );
1834 }
1835
1836
1837 ch_free( ca.tline );
1838 ch_free( ca.argv );
1839
1840 assert( rc == 0 );
1841 }
1842
1843 } else if ( mt->mt_rwmap.rwm_rw != NULL ) {
1844 if ( mt->mt_rwmap.rwm_bva_rewrite ) {
1845 ber_bvarray_free( mt->mt_rwmap.rwm_bva_rewrite );
1846 mt->mt_rwmap.rwm_bva_rewrite = NULL;
1847 }
1848 if ( mt->mt_rwmap.rwm_rw )
1849 rewrite_info_delete( &mt->mt_rwmap.rwm_rw );
1850
1851 meta_rwi_init( &mt->mt_rwmap.rwm_rw );
1852 }
1853 }
1854 break;
1855
1856 case LDAP_BACK_CFG_MAP:
1857 if ( mt->mt_rwmap.rwm_bva_map ) {
1858 ber_bvarray_free( mt->mt_rwmap.rwm_bva_map );
1859 mt->mt_rwmap.rwm_bva_map = NULL;
1860 }
1861 meta_back_map_free( &mt->mt_rwmap.rwm_oc );
1862 meta_back_map_free( &mt->mt_rwmap.rwm_at );
1863 mt->mt_rwmap.rwm_oc.drop_missing = 0;
1864 mt->mt_rwmap.rwm_at.drop_missing = 0;
1865 break;
1866
1867 case LDAP_BACK_CFG_SUBTREE_EX:
1868 case LDAP_BACK_CFG_SUBTREE_IN:
1869 /* can only be one of exclude or include */
1870 if (( c->type == LDAP_BACK_CFG_SUBTREE_EX ) ^ mt->mt_subtree_exclude ) {
1871 rc = 1;
1872 break;
1873 }
1874 if ( c->valx < 0 ) {
1875 meta_subtree_destroy( mt->mt_subtree );
1876 mt->mt_subtree = NULL;
1877 } else {
1878 metasubtree_t *ms, **mprev;
1879 for (i=0, mprev = &mt->mt_subtree, ms = *mprev; ms; ms = *mprev) {
1880 if ( i == c->valx ) {
1881 *mprev = ms->ms_next;
1882 meta_subtree_free( ms );
1883 break;
1884 }
1885 i++;
1886 mprev = &ms->ms_next;
1887 }
1888 if ( i != c->valx )
1889 rc = 1;
1890 }
1891 break;
1892
1893 case LDAP_BACK_CFG_FILTER:
1894 if ( c->valx < 0 ) {
1895 meta_filter_destroy( mt->mt_filter );
1896 mt->mt_filter = NULL;
1897 } else {
1898 metafilter_t *mf, **mprev;
1899 for (i=0, mprev = &mt->mt_filter, mf = *mprev; mf; mf = *mprev) {
1900 if ( i == c->valx ) {
1901 *mprev = mf->mf_next;
1902 meta_filter_free( mf );
1903 break;
1904 }
1905 i++;
1906 mprev = &mf->mf_next;
1907 }
1908 if ( i != c->valx )
1909 rc = 1;
1910 }
1911 break;
1912
1913 case LDAP_BACK_CFG_KEEPALIVE:
1914 mt->mt_tls.sb_keepalive.sk_idle = 0;
1915 mt->mt_tls.sb_keepalive.sk_probes = 0;
1916 mt->mt_tls.sb_keepalive.sk_interval = 0;
1917 break;
1918
1919 case LDAP_BACK_CFG_TCP_USER_TIMEOUT:
1920 mt->mt_tls.sb_tcp_user_timeout = 0;
1921 break;
1922
1923 default:
1924 rc = 1;
1925 break;
1926 }
1927
1928 return rc;
1929 }
1930
1931 if ( c->op == SLAP_CONFIG_ADD ) {
1932 if ( c->type >= LDAP_BACK_CFG_LAST_BASE ) {
1933 /* exclude CFG_URI from this check */
1934 if ( c->type > LDAP_BACK_CFG_LAST_BOTH ) {
1935 if ( !mi->mi_ntargets ) {
1936 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1937 "need \"uri\" directive first" );
1938 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1939 return 1;
1940 }
1941 }
1942 if ( mi->mi_ntargets ) {
1943 mt = mi->mi_targets[ mi->mi_ntargets-1 ];
1944 mc = &mt->mt_mc;
1945 } else {
1946 mt = NULL;
1947 mc = &mi->mi_mc;
1948 }
1949 }
1950 } else {
1951 if ( c->table == Cft_Database ) {
1952 mt = NULL;
1953 mc = &mi->mi_mc;
1954 } else {
1955 mt = c->ca_private;
1956 if ( mt )
1957 mc = &mt->mt_mc;
1958 else
1959 mc = NULL;
1960 }
1961 }
1962
1963 switch( c->type ) {
1964 case LDAP_BACK_CFG_URI: {
1965 LDAPURLDesc *ludp;
1966 struct berval dn;
1967 int j;
1968
1969 char **uris = NULL;
1970
1971 if ( c->be->be_nsuffix == NULL ) {
1972 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1973 "the suffix must be defined before any target" );
1974 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1975 return 1;
1976 }
1977
1978 i = mi->mi_ntargets++;
1979
1980 mi->mi_targets = ( metatarget_t ** )ch_realloc( mi->mi_targets,
1981 sizeof( metatarget_t * ) * mi->mi_ntargets );
1982 if ( mi->mi_targets == NULL ) {
1983 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1984 "out of memory while storing server name"
1985 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
1986 c->argv[0] );
1987 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1988 return 1;
1989 }
1990
1991 if ( meta_back_new_target( &mi->mi_targets[ i ] ) != 0 ) {
1992 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1993 "unable to init server"
1994 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
1995 c->argv[0] );
1996 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
1997 return 1;
1998 }
1999
2000 mt = mi->mi_targets[ i ];
2001
2002 mt->mt_rebind_f = mi->mi_rebind_f;
2003 mt->mt_urllist_f = mi->mi_urllist_f;
2004 mt->mt_urllist_p = mt;
2005
2006 if ( META_BACK_QUARANTINE( mi ) ) {
2007 ldap_pvt_thread_mutex_init( &mt->mt_quarantine_mutex );
2008 }
2009 mt->mt_mc = mi->mi_mc;
2010
2011 for ( j = 1; j < c->argc; j++ ) {
2012 char **tmpuris = ldap_str2charray( c->argv[ j ], "\t" );
2013
2014 if ( tmpuris == NULL ) {
2015 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2016 "unable to parse URIs #%d"
2017 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
2018 j-1, c->argv[0] );
2019 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2020 return 1;
2021 }
2022
2023 if ( j == 1 ) {
2024 uris = tmpuris;
2025
2026 } else {
2027 ldap_charray_merge( &uris, tmpuris );
2028 ldap_charray_free( tmpuris );
2029 }
2030 }
2031
2032 for ( j = 0; uris[ j ] != NULL; j++ ) {
2033 char *tmpuri = NULL;
2034
2035 /*
2036 * uri MUST be legal!
2037 */
2038 if ( ldap_url_parselist_ext( &ludp, uris[ j ], "\t",
2039 LDAP_PVT_URL_PARSE_NONE ) != LDAP_SUCCESS
2040 || ludp->lud_next != NULL )
2041 {
2042 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2043 "unable to parse URI #%d"
2044 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
2045 j-1, c->argv[0] );
2046 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2047 ldap_charray_free( uris );
2048 return 1;
2049 }
2050
2051 if ( j == 0 ) {
2052
2053 /*
2054 * uri MUST have the <dn> part!
2055 */
2056 if ( ludp->lud_dn == NULL ) {
2057 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2058 "missing <naming context> "
2059 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
2060 c->argv[0] );
2061 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2062 ldap_free_urllist( ludp );
2063 ldap_charray_free( uris );
2064 return 1;
2065 }
2066
2067 /*
2068 * copies and stores uri and suffix
2069 */
2070 ber_str2bv( ludp->lud_dn, 0, 0, &dn );
2071 rc = dnPrettyNormal( NULL, &dn, &mt->mt_psuffix,
2072 &mt->mt_nsuffix, NULL );
2073 if ( rc != LDAP_SUCCESS ) {
2074 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2075 "target DN is invalid \"%s\"",
2076 c->argv[1] );
2077 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2078 ldap_free_urllist( ludp );
2079 ldap_charray_free( uris );
2080 return( 1 );
2081 }
2082
2083 ludp->lud_dn[ 0 ] = '\0';
2084
2085 switch ( ludp->lud_scope ) {
2086 case LDAP_SCOPE_DEFAULT:
2087 mt->mt_scope = LDAP_SCOPE_SUBTREE;
2088 break;
2089
2090 case LDAP_SCOPE_SUBTREE:
2091 case LDAP_SCOPE_SUBORDINATE:
2092 mt->mt_scope = ludp->lud_scope;
2093 break;
2094
2095 default:
2096 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2097 "invalid scope for target \"%s\"",
2098 c->argv[1] );
2099 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2100 ldap_free_urllist( ludp );
2101 ldap_charray_free( uris );
2102 return( 1 );
2103 }
2104
2105 } else {
2106 /* check all, to apply the scope check on the first one */
2107 if ( ludp->lud_dn != NULL && ludp->lud_dn[ 0 ] != '\0' ) {
2108 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2109 "multiple URIs must have no DN part" );
2110 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2111 ldap_free_urllist( ludp );
2112 ldap_charray_free( uris );
2113 return( 1 );
2114
2115 }
2116 }
2117
2118 tmpuri = ldap_url_list2urls( ludp );
2119 ldap_free_urllist( ludp );
2120 if ( tmpuri == NULL ) {
2121 snprintf( c->cr_msg, sizeof( c->cr_msg ), "no memory?" );
2122 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2123 ldap_charray_free( uris );
2124 return( 1 );
2125 }
2126 ldap_memfree( uris[ j ] );
2127 uris[ j ] = tmpuri;
2128 }
2129
2130 mt->mt_uri = ldap_charray2str( uris, " " );
2131 ldap_charray_free( uris );
2132 if ( mt->mt_uri == NULL) {
2133 snprintf( c->cr_msg, sizeof( c->cr_msg ), "no memory?" );
2134 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2135 return( 1 );
2136 }
2137
2138 /*
2139 * uri MUST be a branch of suffix!
2140 */
2141 for ( j = 0; !BER_BVISNULL( &c->be->be_nsuffix[ j ] ); j++ ) {
2142 if ( dnIsSuffix( &mt->mt_nsuffix, &c->be->be_nsuffix[ j ] ) ) {
2143 break;
2144 }
2145 }
2146
2147 if ( BER_BVISNULL( &c->be->be_nsuffix[ j ] ) ) {
2148 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2149 "<naming context> of URI must be within the naming context of this database." );
2150 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2151 return 1;
2152 }
2153 c->ca_private = mt;
2154 config_push_cleanup( c, meta_cf_cleanup );
2155 } break;
2156 case LDAP_BACK_CFG_SUBTREE_EX:
2157 case LDAP_BACK_CFG_SUBTREE_IN:
2158 /* subtree-exclude */
2159 if ( meta_subtree_config( mt, c )) {
2160 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2161 return 1;
2162 }
2163 break;
2164
2165 case LDAP_BACK_CFG_FILTER: {
2166 metafilter_t *mf, **m2;
2167 mf = ch_calloc( 1, sizeof( metafilter_t ));
2168 rc = regcomp( &mf->mf_regex, c->argv[1], REG_EXTENDED );
2169 if ( rc ) {
2170 char regerr[ SLAP_TEXT_BUFLEN ];
2171 regerror( rc, &mf->mf_regex, regerr, sizeof(regerr) );
2172 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2173 "regular expression \"%s\" bad because of %s",
2174 c->argv[1], regerr );
2175 ch_free( mf );
2176 return 1;
2177 }
2178 ber_str2bv( c->argv[1], 0, 1, &mf->mf_regex_pattern );
2179 for ( m2 = &mt->mt_filter; *m2; m2 = &(*m2)->mf_next )
2180 ;
2181 *m2 = mf;
2182 } break;
2183
2184 case LDAP_BACK_CFG_DEFAULT_T:
2185 /* default target directive */
2186 i = mi->mi_ntargets - 1;
2187
2188 if ( c->argc == 1 ) {
2189 if ( i < 0 ) {
2190 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2191 "\"%s\" alone must be inside a \"uri\" directive",
2192 c->argv[0] );
2193 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2194 return 1;
2195 }
2196 mi->mi_defaulttarget = i;
2197
2198 } else {
2199 if ( strcasecmp( c->argv[ 1 ], "none" ) == 0 ) {
2200 if ( i >= 0 ) {
2201 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2202 "\"%s none\" should go before uri definitions",
2203 c->argv[0] );
2204 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2205 }
2206 mi->mi_defaulttarget = META_DEFAULT_TARGET_NONE;
2207
2208 } else {
2209
2210 if ( lutil_atoi( &mi->mi_defaulttarget, c->argv[ 1 ] ) != 0
2211 || mi->mi_defaulttarget < 0
2212 || mi->mi_defaulttarget >= i - 1 )
2213 {
2214 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2215 "illegal target number %d",
2216 mi->mi_defaulttarget );
2217 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2218 return 1;
2219 }
2220 }
2221 }
2222 break;
2223
2224 case LDAP_BACK_CFG_DNCACHE_TTL:
2225 /* ttl of dn cache */
2226 if ( strcasecmp( c->argv[ 1 ], "forever" ) == 0 ) {
2227 mi->mi_cache.ttl = META_DNCACHE_FOREVER;
2228
2229 } else if ( strcasecmp( c->argv[ 1 ], "disabled" ) == 0 ) {
2230 mi->mi_cache.ttl = META_DNCACHE_DISABLED;
2231
2232 } else {
2233 unsigned long t;
2234
2235 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
2236 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2237 "unable to parse dncache ttl \"%s\"",
2238 c->argv[ 1 ] );
2239 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2240 return 1;
2241 }
2242 mi->mi_cache.ttl = (time_t)t;
2243 }
2244 break;
2245
2246 case LDAP_BACK_CFG_NETWORK_TIMEOUT: {
2247 /* network timeout when connecting to ldap servers */
2248 unsigned long t;
2249
2250 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) {
2251 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2252 "unable to parse network timeout \"%s\"",
2253 c->argv[ 1 ] );
2254 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2255 return 1;
2256 }
2257 mc->mc_network_timeout = (time_t)t;
2258 } break;
2259
2260 case LDAP_BACK_CFG_IDLE_TIMEOUT: {
2261 /* idle timeout when connecting to ldap servers */
2262 unsigned long t;
2263
2264 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) {
2265 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2266 "unable to parse idle timeout \"%s\"",
2267 c->argv[ 1 ] );
2268 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2269 return 1;
2270
2271 }
2272 mi->mi_idle_timeout = (time_t)t;
2273 } break;
2274
2275 case LDAP_BACK_CFG_CONN_TTL: {
2276 /* conn ttl */
2277 unsigned long t;
2278
2279 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) {
2280 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2281 "unable to parse conn ttl \"%s\"",
2282 c->argv[ 1 ] );
2283 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2284 return 1;
2285
2286 }
2287 mi->mi_conn_ttl = (time_t)t;
2288 } break;
2289
2290 case LDAP_BACK_CFG_BIND_TIMEOUT:
2291 /* bind timeout when connecting to ldap servers */
2292 mc->mc_bind_timeout.tv_sec = c->value_ulong/1000000;
2293 mc->mc_bind_timeout.tv_usec = c->value_ulong%1000000;
2294 break;
2295
2296 case LDAP_BACK_CFG_REBIND:
2297 /* save bind creds for referral rebinds? */
2298 if ( c->argc == 1 || c->value_int ) {
2299 mc->mc_flags |= LDAP_BACK_F_SAVECRED;
2300 } else {
2301 mc->mc_flags &= ~LDAP_BACK_F_SAVECRED;
2302 }
2303 break;
2304
2305 case LDAP_BACK_CFG_CHASE:
2306 if ( c->argc == 1 || c->value_int ) {
2307 mc->mc_flags |= LDAP_BACK_F_CHASE_REFERRALS;
2308 } else {
2309 mc->mc_flags &= ~LDAP_BACK_F_CHASE_REFERRALS;
2310 }
2311 break;
2312
2313 case LDAP_BACK_CFG_TLS:
2314 i = verb_to_mask( c->argv[1], tls_mode );
2315 if ( BER_BVISNULL( &tls_mode[i].word ) ) {
2316 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2317 "%s unknown argument \"%s\"",
2318 c->argv[0], c->argv[1] );
2319 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2320 return 1;
2321 }
2322 mc->mc_flags &= ~LDAP_BACK_F_TLS_MASK;
2323 mc->mc_flags |= tls_mode[i].mask;
2324
2325 if ( c->argc > 2 ) {
2326 if ( c->op == SLAP_CONFIG_ADD && mi->mi_ntargets == 0 ) {
2327 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2328 "need \"uri\" directive first" );
2329 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2330 return 1;
2331 }
2332
2333 for ( i = 2; i < c->argc; i++ ) {
2334 if ( bindconf_tls_parse( c->argv[i], &mt->mt_tls ))
2335 return 1;
2336 }
2337 bindconf_tls_defaults( &mt->mt_tls );
2338 }
2339 break;
2340
2341 case LDAP_BACK_CFG_T_F:
2342 i = verb_to_mask( c->argv[1], t_f_mode );
2343 if ( BER_BVISNULL( &t_f_mode[i].word ) ) {
2344 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2345 "%s unknown argument \"%s\"",
2346 c->argv[0], c->argv[1] );
2347 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2348 return 1;
2349 }
2350 mc->mc_flags &= ~LDAP_BACK_F_T_F_MASK2;
2351 mc->mc_flags |= t_f_mode[i].mask;
2352 break;
2353
2354 case LDAP_BACK_CFG_ONERR:
2355 /* onerr? */
2356 i = verb_to_mask( c->argv[1], onerr_mode );
2357 if ( BER_BVISNULL( &onerr_mode[i].word ) ) {
2358 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2359 "%s unknown argument \"%s\"",
2360 c->argv[0], c->argv[1] );
2361 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2362 return 1;
2363 }
2364 mi->mi_flags &= ~META_BACK_F_ONERR_MASK;
2365 mi->mi_flags |= onerr_mode[i].mask;
2366 break;
2367
2368 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER:
2369 /* bind-defer? */
2370 if ( c->argc == 1 || c->value_int ) {
2371 mi->mi_flags |= META_BACK_F_DEFER_ROOTDN_BIND;
2372 } else {
2373 mi->mi_flags &= ~META_BACK_F_DEFER_ROOTDN_BIND;
2374 }
2375 break;
2376
2377 case LDAP_BACK_CFG_SINGLECONN:
2378 /* single-conn? */
2379 if ( mi->mi_ntargets > 0 ) {
2380 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2381 "\"%s\" must appear before target definitions",
2382 c->argv[0] );
2383 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2384 return( 1 );
2385 }
2386 if ( c->value_int ) {
2387 mi->mi_flags |= LDAP_BACK_F_SINGLECONN;
2388 } else {
2389 mi->mi_flags &= ~LDAP_BACK_F_SINGLECONN;
2390 }
2391 break;
2392
2393 case LDAP_BACK_CFG_USETEMP:
2394 /* use-temporaries? */
2395 if ( mi->mi_ntargets > 0 ) {
2396 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2397 "\"%s\" must appear before target definitions",
2398 c->argv[0] );
2399 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2400 return( 1 );
2401 }
2402 if ( c->value_int ) {
2403 mi->mi_flags |= LDAP_BACK_F_USE_TEMPORARIES;
2404 } else {
2405 mi->mi_flags &= ~LDAP_BACK_F_USE_TEMPORARIES;
2406 }
2407 break;
2408
2409 case LDAP_BACK_CFG_CONNPOOLMAX:
2410 /* privileged connections pool max size ? */
2411 if ( mi->mi_ntargets > 0 ) {
2412 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2413 "\"%s\" must appear before target definitions",
2414 c->argv[0] );
2415 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2416 return( 1 );
2417 }
2418
2419 if ( c->value_int < LDAP_BACK_CONN_PRIV_MIN
2420 || c->value_int > LDAP_BACK_CONN_PRIV_MAX )
2421 {
2422 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2423 "invalid max size " "of privileged "
2424 "connections pool \"%s\" "
2425 "in \"conn-pool-max <n> "
2426 "(must be between %d and %d)\"",
2427 c->argv[ 1 ],
2428 LDAP_BACK_CONN_PRIV_MIN,
2429 LDAP_BACK_CONN_PRIV_MAX );
2430 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2431 return 1;
2432 }
2433 mi->mi_conn_priv_max = c->value_int;
2434 break;
2435
2436 case LDAP_BACK_CFG_CANCEL:
2437 i = verb_to_mask( c->argv[1], cancel_mode );
2438 if ( BER_BVISNULL( &cancel_mode[i].word ) ) {
2439 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2440 "%s unknown argument \"%s\"",
2441 c->argv[0], c->argv[1] );
2442 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2443 return 1;
2444 }
2445 mc->mc_flags &= ~LDAP_BACK_F_CANCEL_MASK2;
2446 mc->mc_flags |= cancel_mode[i].mask;
2447 break;
2448
2449 case LDAP_BACK_CFG_TIMEOUT:
2450 for ( i = 1; i < c->argc; i++ ) {
2451 if ( isdigit( (unsigned char) c->argv[ i ][ 0 ] ) ) {
2452 int j;
2453 unsigned u;
2454
2455 if ( lutil_atoux( &u, c->argv[ i ], 0 ) != 0 ) {
2456 snprintf( c->cr_msg, sizeof( c->cr_msg),
2457 "unable to parse timeout \"%s\"",
2458 c->argv[ i ] );
2459 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2460 return 1;
2461 }
2462
2463 for ( j = 0; j < SLAP_OP_LAST; j++ ) {
2464 mc->mc_timeout[ j ] = u;
2465 }
2466
2467 continue;
2468 }
2469
2470 if ( slap_cf_aux_table_parse( c->argv[ i ], mc->mc_timeout, timeout_table, "slapd-meta timeout" ) ) {
2471 snprintf( c->cr_msg, sizeof( c->cr_msg),
2472 "unable to parse timeout \"%s\"",
2473 c->argv[ i ] );
2474 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2475 return 1;
2476 }
2477 }
2478 break;
2479
2480 case LDAP_BACK_CFG_PSEUDOROOTDN:
2481 /* name to use as pseudo-root dn */
2482 /*
2483 * exact replacement:
2484 *
2485
2486 idassert-bind bindmethod=simple
2487 binddn=<pseudorootdn>
2488 credentials=<pseudorootpw>
2489 mode=none
2490 flags=non-prescriptive
2491 idassert-authzFrom "dn:<rootdn>"
2492
2493 * so that only when authc'd as <rootdn> the proxying occurs
2494 * rebinding as the <pseudorootdn> without proxyAuthz.
2495 */
2496
2497 Debug( LDAP_DEBUG_ANY,
2498 "%s: \"pseudorootdn\", \"pseudorootpw\" are no longer supported; "
2499 "use \"idassert-bind\" and \"idassert-authzFrom\" instead.\n",
2500 c->log );
2501
2502 {
2503 char binddn[ SLAP_TEXT_BUFLEN ];
2504 char *cargv[] = {
2505 "idassert-bind",
2506 "bindmethod=simple",
2507 NULL,
2508 "mode=none",
2509 "flags=non-prescriptive",
2510 NULL
2511 };
2512 char **oargv;
2513 int oargc;
2514 int cargc = 5;
2515 int rc;
2516
2517
2518 if ( BER_BVISNULL( &c->be->be_rootndn ) ) {
2519 Debug( LDAP_DEBUG_ANY, "%s: \"pseudorootpw\": \"rootdn\" must be defined first.\n",
2520 c->log );
2521 return 1;
2522 }
2523
2524 if ( sizeof( binddn ) <= (unsigned) snprintf( binddn,
2525 sizeof( binddn ), "binddn=%s", c->argv[ 1 ] ))
2526 {
2527 Debug( LDAP_DEBUG_ANY, "%s: \"pseudorootdn\" too long.\n",
2528 c->log );
2529 return 1;
2530 }
2531 cargv[ 2 ] = binddn;
2532
2533 oargv = c->argv;
2534 oargc = c->argc;
2535 c->argv = cargv;
2536 c->argc = cargc;
2537 rc = mi->mi_ldap_extra->idassert_parse( c, &mt->mt_idassert );
2538 c->argv = oargv;
2539 c->argc = oargc;
2540 if ( rc == 0 ) {
2541 struct berval bv;
2542
2543 if ( mt->mt_idassert_authz != NULL ) {
2544 Debug( LDAP_DEBUG_ANY, "%s: \"idassert-authzFrom\" already defined (discarded).\n",
2545 c->log );
2546 ber_bvarray_free( mt->mt_idassert_authz );
2547 mt->mt_idassert_authz = NULL;
2548 }
2549
2550 assert( !BER_BVISNULL( &mt->mt_idassert_authcDN ) );
2551
2552 bv.bv_len = STRLENOF( "dn:" ) + c->be->be_rootndn.bv_len;
2553 bv.bv_val = ch_malloc( bv.bv_len + 1 );
2554 AC_MEMCPY( bv.bv_val, "dn:", STRLENOF( "dn:" ) );
2555 AC_MEMCPY( &bv.bv_val[ STRLENOF( "dn:" ) ], c->be->be_rootndn.bv_val, c->be->be_rootndn.bv_len + 1 );
2556
2557 ber_bvarray_add( &mt->mt_idassert_authz, &bv );
2558 }
2559
2560 return rc;
2561 }
2562 break;
2563
2564 case LDAP_BACK_CFG_PSEUDOROOTPW:
2565 /* password to use as pseudo-root */
2566 Debug( LDAP_DEBUG_ANY,
2567 "%s: \"pseudorootdn\", \"pseudorootpw\" are no longer supported; "
2568 "use \"idassert-bind\" and \"idassert-authzFrom\" instead.\n",
2569 c->log );
2570
2571 if ( BER_BVISNULL( &mt->mt_idassert_authcDN ) ) {
2572 Debug( LDAP_DEBUG_ANY, "%s: \"pseudorootpw\": \"pseudorootdn\" must be defined first.\n",
2573 c->log );
2574 return 1;
2575 }
2576
2577 if ( !BER_BVISNULL( &mt->mt_idassert_passwd ) ) {
2578 memset( mt->mt_idassert_passwd.bv_val, 0,
2579 mt->mt_idassert_passwd.bv_len );
2580 ber_memfree( mt->mt_idassert_passwd.bv_val );
2581 }
2582 ber_str2bv( c->argv[ 1 ], 0, 1, &mt->mt_idassert_passwd );
2583 break;
2584
2585 case LDAP_BACK_CFG_IDASSERT_BIND:
2586 /* idassert-bind */
2587 rc = mi->mi_ldap_extra->idassert_parse( c, &mt->mt_idassert );
2588 break;
2589
2590 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM:
2591 /* idassert-authzFrom */
2592 rc = mi->mi_ldap_extra->idassert_authzfrom_parse( c, &mt->mt_idassert );
2593 break;
2594
2595 case LDAP_BACK_CFG_QUARANTINE:
2596 /* quarantine */
2597 if ( META_BACK_CMN_QUARANTINE( mc ) )
2598 {
2599 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2600 "quarantine already defined" );
2601 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2602 return 1;
2603 }
2604
2605 if ( mt ) {
2606 mc->mc_quarantine.ri_interval = NULL;
2607 mc->mc_quarantine.ri_num = NULL;
2608 if ( !META_BACK_QUARANTINE( mi ) ) {
2609 ldap_pvt_thread_mutex_init( &mt->mt_quarantine_mutex );
2610 }
2611 }
2612
2613 if ( mi->mi_ldap_extra->retry_info_parse( c->argv[ 1 ], &mc->mc_quarantine, c->cr_msg, sizeof( c->cr_msg ) ) ) {
2614 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2615 return 1;
2616 }
2617
2618 mc->mc_flags |= LDAP_BACK_F_QUARANTINE;
2619 break;
2620
2621 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
2622 case LDAP_BACK_CFG_ST_REQUEST:
2623 /* session tracking request */
2624 if ( c->value_int ) {
2625 mc->mc_flags |= LDAP_BACK_F_ST_REQUEST;
2626 } else {
2627 mc->mc_flags &= ~LDAP_BACK_F_ST_REQUEST;
2628 }
2629 break;
2630 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
2631
2632 case LDAP_BACK_CFG_SUFFIXM: /* FALLTHRU */
2633 case LDAP_BACK_CFG_REWRITE: {
2634 /* rewrite stuff ... */
2635 ConfigArgs ca = { 0 };
2636 char *line, **argv;
2637 struct rewrite_info *rwi;
2638 int cnt = 0, argc, ix = c->valx;
2639
2640 if ( mt->mt_rwmap.rwm_bva_rewrite ) {
2641 for ( ; !BER_BVISNULL( &mt->mt_rwmap.rwm_bva_rewrite[ cnt ] ); cnt++ )
2642 /* count */ ;
2643 }
2644
2645 if ( ix >= cnt || ix < 0 ) {
2646 ix = cnt;
2647 } else {
2648 rwi = mt->mt_rwmap.rwm_rw;
2649
2650 mt->mt_rwmap.rwm_rw = NULL;
2651 rc = meta_rwi_init( &mt->mt_rwmap.rwm_rw );
2652
2653 /* re-parse all rewrite rules, up to the one
2654 * that needs to be added */
2655 ca.be = c->be;
2656 ca.fname = c->fname;
2657 ca.lineno = c->lineno;
2658 for ( i = 0; i < ix; i++ ) {
2659 ca.line = mt->mt_rwmap.rwm_bva_rewrite[ i ].bv_val;
2660 ca.argc = 0;
2661 config_fp_parse_line( &ca );
2662
2663 if ( !strcasecmp( ca.argv[0], "suffixmassage" )) {
2664 rc = meta_suffixm_config( &ca, ca.argc, ca.argv, mt );
2665 } else {
2666 rc = rewrite_parse( mt->mt_rwmap.rwm_rw,
2667 c->fname, c->lineno, ca.argc, ca.argv );
2668 }
2669 assert( rc == 0 );
2670 ch_free( ca.argv );
2671 ch_free( ca.tline );
2672 }
2673 }
2674 argc = c->argc;
2675 argv = c->argv;
2676 if ( c->op != SLAP_CONFIG_ADD ) {
2677 argc--;
2678 argv++;
2679 }
2680 /* add the new rule */
2681 if ( !strcasecmp( argv[0], "suffixmassage" )) {
2682 rc = meta_suffixm_config( c, argc, argv, mt );
2683 } else {
2684 rc = rewrite_parse( mt->mt_rwmap.rwm_rw,
2685 c->fname, c->lineno, argc, argv );
2686 }
2687 if ( rc ) {
2688 if ( ix < cnt ) {
2689 rewrite_info_delete( &mt->mt_rwmap.rwm_rw );
2690 mt->mt_rwmap.rwm_rw = rwi;
2691 }
2692 return 1;
2693 }
2694 if ( ix < cnt ) {
2695 for ( ; i < cnt; i++ ) {
2696 ca.line = mt->mt_rwmap.rwm_bva_rewrite[ i ].bv_val;
2697 ca.argc = 0;
2698 config_fp_parse_line( &ca );
2699
2700 if ( !strcasecmp( ca.argv[0], "suffixmassage" )) {
2701 rc = meta_suffixm_config( &ca, ca.argc, ca.argv, mt );
2702 } else {
2703 rc = rewrite_parse( mt->mt_rwmap.rwm_rw,
2704 c->fname, c->lineno, ca.argc, argv );
2705 }
2706 assert( rc == 0 );
2707 ch_free( ca.argv );
2708 ch_free( ca.tline );
2709 }
2710 }
2711
2712 /* save the rule info */
2713 line = ldap_charray2str( argv, "\" \"" );
2714 if ( line != NULL ) {
2715 struct berval bv;
2716 int len = strlen( argv[ 0 ] );
2717
2718 ber_str2bv( line, 0, 0, &bv );
2719 AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
2720 bv.bv_len - ( len + 1 ));
2721 bv.bv_val[ bv.bv_len - 1] = '"';
2722 ber_bvarray_add( &mt->mt_rwmap.rwm_bva_rewrite, &bv );
2723 /* move it to the right slot */
2724 if ( ix < cnt ) {
2725 for ( i=cnt; i>ix; i-- )
2726 mt->mt_rwmap.rwm_bva_rewrite[i+1] = mt->mt_rwmap.rwm_bva_rewrite[i];
2727 mt->mt_rwmap.rwm_bva_rewrite[i] = bv;
2728
2729 /* destroy old rules */
2730 rewrite_info_delete( &rwi );
2731 }
2732 }
2733 } break;
2734
2735 case LDAP_BACK_CFG_MAP: {
2736 /* objectclass/attribute mapping */
2737 ConfigArgs ca = { 0 };
2738 char *argv[5];
2739 struct ldapmap rwm_oc;
2740 struct ldapmap rwm_at;
2741 int cnt = 0, ix = c->valx;
2742
2743 if ( mt->mt_rwmap.rwm_bva_map ) {
2744 for ( ; !BER_BVISNULL( &mt->mt_rwmap.rwm_bva_map[ cnt ] ); cnt++ )
2745 /* count */ ;
2746 }
2747
2748 if ( ix >= cnt || ix < 0 ) {
2749 ix = cnt;
2750 } else {
2751 rwm_oc = mt->mt_rwmap.rwm_oc;
2752 rwm_at = mt->mt_rwmap.rwm_at;
2753
2754 memset( &mt->mt_rwmap.rwm_oc, 0, sizeof( mt->mt_rwmap.rwm_oc ) );
2755 memset( &mt->mt_rwmap.rwm_at, 0, sizeof( mt->mt_rwmap.rwm_at ) );
2756
2757 /* re-parse all mappings, up to the one
2758 * that needs to be added */
2759 argv[0] = c->argv[0];
2760 ca.fname = c->fname;
2761 ca.lineno = c->lineno;
2762 for ( i = 0; i < ix; i++ ) {
2763 ca.line = mt->mt_rwmap.rwm_bva_map[ i ].bv_val;
2764 ca.argc = 0;
2765 config_fp_parse_line( &ca );
2766
2767 argv[1] = ca.argv[0];
2768 argv[2] = ca.argv[1];
2769 argv[3] = ca.argv[2];
2770 argv[4] = ca.argv[3];
2771 ch_free( ca.argv );
2772 ca.argv = argv;
2773 ca.argc++;
2774 rc = ldap_back_map_config( &ca, &mt->mt_rwmap.rwm_oc,
2775 &mt->mt_rwmap.rwm_at );
2776
2777 ch_free( ca.tline );
2778 ca.tline = NULL;
2779 ca.argv = NULL;
2780
2781 /* in case of failure, restore
2782 * the existing mapping */
2783 if ( rc ) {
2784 goto map_fail;
2785 }
2786 }
2787 }
2788 /* add the new mapping */
2789 rc = ldap_back_map_config( c, &mt->mt_rwmap.rwm_oc,
2790 &mt->mt_rwmap.rwm_at );
2791 if ( rc ) {
2792 goto map_fail;
2793 }
2794
2795 if ( ix < cnt ) {
2796 for ( ; i<cnt ; cnt++ ) {
2797 ca.line = mt->mt_rwmap.rwm_bva_map[ i ].bv_val;
2798 ca.argc = 0;
2799 config_fp_parse_line( &ca );
2800
2801 argv[1] = ca.argv[0];
2802 argv[2] = ca.argv[1];
2803 argv[3] = ca.argv[2];
2804 argv[4] = ca.argv[3];
2805
2806 ch_free( ca.argv );
2807 ca.argv = argv;
2808 ca.argc++;
2809 rc = ldap_back_map_config( &ca, &mt->mt_rwmap.rwm_oc,
2810 &mt->mt_rwmap.rwm_at );
2811
2812 ch_free( ca.tline );
2813 ca.tline = NULL;
2814 ca.argv = NULL;
2815
2816 /* in case of failure, restore
2817 * the existing mapping */
2818 if ( rc ) {
2819 goto map_fail;
2820 }
2821 }
2822 }
2823
2824 /* save the map info */
2825 argv[0] = ldap_charray2str( &c->argv[ 1 ], " " );
2826 if ( argv[0] != NULL ) {
2827 struct berval bv;
2828 ber_str2bv( argv[0], 0, 0, &bv );
2829 ber_bvarray_add( &mt->mt_rwmap.rwm_bva_map, &bv );
2830 /* move it to the right slot */
2831 if ( ix < cnt ) {
2832 for ( i=cnt; i>ix; i-- )
2833 mt->mt_rwmap.rwm_bva_map[i+1] = mt->mt_rwmap.rwm_bva_map[i];
2834 mt->mt_rwmap.rwm_bva_map[i] = bv;
2835
2836 /* destroy old mapping */
2837 meta_back_map_free( &rwm_oc );
2838 meta_back_map_free( &rwm_at );
2839 }
2840 }
2841 break;
2842
2843 map_fail:;
2844 if ( ix < cnt ) {
2845 meta_back_map_free( &mt->mt_rwmap.rwm_oc );
2846 meta_back_map_free( &mt->mt_rwmap.rwm_at );
2847 mt->mt_rwmap.rwm_oc = rwm_oc;
2848 mt->mt_rwmap.rwm_at = rwm_at;
2849 }
2850 } break;
2851
2852 case LDAP_BACK_CFG_NRETRIES: {
2853 int nretries = META_RETRY_UNDEFINED;
2854
2855 if ( strcasecmp( c->argv[ 1 ], "forever" ) == 0 ) {
2856 nretries = META_RETRY_FOREVER;
2857
2858 } else if ( strcasecmp( c->argv[ 1 ], "never" ) == 0 ) {
2859 nretries = META_RETRY_NEVER;
2860
2861 } else {
2862 if ( lutil_atoi( &nretries, c->argv[ 1 ] ) != 0 ) {
2863 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2864 "unable to parse nretries {never|forever|<retries>}: \"%s\"",
2865 c->argv[ 1 ] );
2866 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2867 return 1;
2868 }
2869 }
2870
2871 mc->mc_nretries = nretries;
2872 } break;
2873
2874 case LDAP_BACK_CFG_VERSION:
2875 if ( c->value_int != 0 && ( c->value_int < LDAP_VERSION_MIN || c->value_int > LDAP_VERSION_MAX ) ) {
2876 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2877 "unsupported protocol version \"%s\"",
2878 c->argv[ 1 ] );
2879 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2880 return 1;
2881 }
2882 mc->mc_version = c->value_int;
2883 break;
2884
2885 case LDAP_BACK_CFG_NOREFS:
2886 /* do not return search references */
2887 if ( c->value_int ) {
2888 mc->mc_flags |= LDAP_BACK_F_NOREFS;
2889 } else {
2890 mc->mc_flags &= ~LDAP_BACK_F_NOREFS;
2891 }
2892 break;
2893
2894 case LDAP_BACK_CFG_NOUNDEFFILTER:
2895 /* do not propagate undefined search filters */
2896 if ( c->value_int ) {
2897 mc->mc_flags |= LDAP_BACK_F_NOUNDEFFILTER;
2898 } else {
2899 mc->mc_flags &= ~LDAP_BACK_F_NOUNDEFFILTER;
2900 }
2901 break;
2902
2903 #ifdef SLAPD_META_CLIENT_PR
2904 case LDAP_BACK_CFG_CLIENT_PR:
2905 if ( strcasecmp( c->argv[ 1 ], "accept-unsolicited" ) == 0 ) {
2906 mc->mc_ps = META_CLIENT_PR_ACCEPT_UNSOLICITED;
2907
2908 } else if ( strcasecmp( c->argv[ 1 ], "disable" ) == 0 ) {
2909 mc->mc_ps = META_CLIENT_PR_DISABLE;
2910
2911 } else if ( lutil_atoi( &mc->mc_ps, c->argv[ 1 ] ) || mc->mc_ps < -1 ) {
2912 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2913 "unable to parse client-pr {accept-unsolicited|disable|<size>}: \"%s\"",
2914 c->argv[ 1 ] );
2915 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2916 return( 1 );
2917 }
2918 break;
2919 #endif /* SLAPD_META_CLIENT_PR */
2920
2921 case LDAP_BACK_CFG_KEEPALIVE:
2922 slap_keepalive_parse( ber_bvstrdup(c->argv[1]),
2923 &mt->mt_tls.sb_keepalive, 0, 0, 0);
2924 break;
2925
2926 case LDAP_BACK_CFG_TCP_USER_TIMEOUT:
2927 mt->mt_tls.sb_tcp_user_timeout = c->value_uint;
2928 break;
2929
2930 /* anything else */
2931 default:
2932 return SLAP_CONF_UNKNOWN;
2933 }
2934
2935 return rc;
2936 }
2937
2938 int
meta_back_init_cf(BackendInfo * bi)2939 meta_back_init_cf( BackendInfo *bi )
2940 {
2941 int rc;
2942
2943 /* Make sure we don't exceed the bits reserved for userland */
2944 config_check_userland( LDAP_BACK_CFG_LAST );
2945
2946 bi->bi_cf_ocs = metaocs;
2947
2948 rc = config_register_schema( metacfg, metaocs );
2949 if ( rc ) {
2950 return rc;
2951 }
2952
2953 return 0;
2954 }
2955
2956 static int
ldap_back_map_config(ConfigArgs * c,struct ldapmap * oc_map,struct ldapmap * at_map)2957 ldap_back_map_config(
2958 ConfigArgs *c,
2959 struct ldapmap *oc_map,
2960 struct ldapmap *at_map )
2961 {
2962 struct ldapmap *map;
2963 struct ldapmapping *mapping;
2964 char *src, *dst;
2965 int is_oc = 0;
2966
2967 if ( strcasecmp( c->argv[ 1 ], "objectclass" ) == 0 ) {
2968 map = oc_map;
2969 is_oc = 1;
2970
2971 } else if ( strcasecmp( c->argv[ 1 ], "attribute" ) == 0 ) {
2972 map = at_map;
2973
2974 } else {
2975 snprintf( c->cr_msg, sizeof(c->cr_msg),
2976 "%s unknown argument \"%s\"",
2977 c->argv[0], c->argv[1] );
2978 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
2979 return 1;
2980 }
2981
2982 if ( !is_oc && map->map == NULL ) {
2983 /* only init if required */
2984 ldap_back_map_init( map, &mapping );
2985 }
2986
2987 if ( strcmp( c->argv[ 2 ], "*" ) == 0 ) {
2988 if ( c->argc < 4 || strcmp( c->argv[ 3 ], "*" ) == 0 ) {
2989 map->drop_missing = ( c->argc < 4 );
2990 goto success_return;
2991 }
2992 src = dst = c->argv[ 3 ];
2993
2994 } else if ( c->argc < 4 ) {
2995 src = "";
2996 dst = c->argv[ 2 ];
2997
2998 } else {
2999 src = c->argv[ 2 ];
3000 dst = ( strcmp( c->argv[ 3 ], "*" ) == 0 ? src : c->argv[ 3 ] );
3001 }
3002
3003 if ( ( map == at_map )
3004 && ( strcasecmp( src, "objectclass" ) == 0
3005 || strcasecmp( dst, "objectclass" ) == 0 ) )
3006 {
3007 snprintf( c->cr_msg, sizeof(c->cr_msg),
3008 "objectclass attribute cannot be mapped" );
3009 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3010 return 1;
3011 }
3012
3013 mapping = (struct ldapmapping *)ch_calloc( 2,
3014 sizeof(struct ldapmapping) );
3015 if ( mapping == NULL ) {
3016 snprintf( c->cr_msg, sizeof(c->cr_msg),
3017 "out of memory" );
3018 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3019 return 1;
3020 }
3021 ber_str2bv( src, 0, 1, &mapping[ 0 ].src );
3022 ber_str2bv( dst, 0, 1, &mapping[ 0 ].dst );
3023 mapping[ 1 ].src = mapping[ 0 ].dst;
3024 mapping[ 1 ].dst = mapping[ 0 ].src;
3025
3026 /*
3027 * schema check
3028 */
3029 if ( is_oc ) {
3030 if ( src[ 0 ] != '\0' ) {
3031 if ( oc_bvfind( &mapping[ 0 ].src ) == NULL ) {
3032 Debug( LDAP_DEBUG_ANY,
3033 "%s: warning, source objectClass '%s' should be defined in schema\n",
3034 c->log, src );
3035
3036 /*
3037 * FIXME: this should become an err
3038 */
3039 goto error_return;
3040 }
3041 }
3042
3043 if ( oc_bvfind( &mapping[ 0 ].dst ) == NULL ) {
3044 Debug( LDAP_DEBUG_ANY,
3045 "%s: warning, destination objectClass '%s' is not defined in schema\n",
3046 c->log, dst );
3047 }
3048 } else {
3049 int rc;
3050 const char *text = NULL;
3051 AttributeDescription *ad = NULL;
3052
3053 if ( src[ 0 ] != '\0' ) {
3054 rc = slap_bv2ad( &mapping[ 0 ].src, &ad, &text );
3055 if ( rc != LDAP_SUCCESS ) {
3056 Debug( LDAP_DEBUG_ANY,
3057 "%s: warning, source attributeType '%s' should be defined in schema\n",
3058 c->log, src );
3059
3060 /*
3061 * FIXME: this should become an err
3062 */
3063 /*
3064 * we create a fake "proxied" ad
3065 * and add it here.
3066 */
3067
3068 rc = slap_bv2undef_ad( &mapping[ 0 ].src,
3069 &ad, &text, SLAP_AD_PROXIED );
3070 if ( rc != LDAP_SUCCESS ) {
3071 snprintf( c->cr_msg, sizeof( c->cr_msg ),
3072 "source attributeType \"%s\": %d (%s)",
3073 src, rc, text ? text : "" );
3074 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3075 goto error_return;
3076 }
3077 }
3078
3079 ad = NULL;
3080 }
3081
3082 rc = slap_bv2ad( &mapping[ 0 ].dst, &ad, &text );
3083 if ( rc != LDAP_SUCCESS ) {
3084 Debug( LDAP_DEBUG_ANY,
3085 "%s: warning, destination attributeType '%s' is not defined in schema\n",
3086 c->log, dst );
3087
3088 /*
3089 * we create a fake "proxied" ad
3090 * and add it here.
3091 */
3092
3093 rc = slap_bv2undef_ad( &mapping[ 0 ].dst,
3094 &ad, &text, SLAP_AD_PROXIED );
3095 if ( rc != LDAP_SUCCESS ) {
3096 snprintf( c->cr_msg, sizeof( c->cr_msg ),
3097 "destination attributeType \"%s\": %d (%s)\n",
3098 dst, rc, text ? text : "" );
3099 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3100 return 1;
3101 }
3102 }
3103 }
3104
3105 if ( (src[ 0 ] != '\0' && ldap_avl_find( map->map, (caddr_t)&mapping[ 0 ], mapping_cmp ) != NULL)
3106 || ldap_avl_find( map->remap, (caddr_t)&mapping[ 1 ], mapping_cmp ) != NULL)
3107 {
3108 snprintf( c->cr_msg, sizeof( c->cr_msg ),
3109 "duplicate mapping found." );
3110 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg );
3111 goto error_return;
3112 }
3113
3114 if ( src[ 0 ] != '\0' ) {
3115 ldap_avl_insert( &map->map, (caddr_t)&mapping[ 0 ],
3116 mapping_cmp, mapping_dup );
3117 }
3118 ldap_avl_insert( &map->remap, (caddr_t)&mapping[ 1 ],
3119 mapping_cmp, mapping_dup );
3120
3121 success_return:;
3122 return 0;
3123
3124 error_return:;
3125 if ( mapping ) {
3126 ch_free( mapping[ 0 ].src.bv_val );
3127 ch_free( mapping[ 0 ].dst.bv_val );
3128 ch_free( mapping );
3129 }
3130
3131 return 1;
3132 }
3133
3134
3135 static char *
suffix_massage_regexize(const char * s)3136 suffix_massage_regexize( const char *s )
3137 {
3138 char *res, *ptr;
3139 const char *p, *r;
3140 int i;
3141
3142 if ( s[ 0 ] == '\0' ) {
3143 return ch_strdup( "^(.+)$" );
3144 }
3145
3146 for ( i = 0, p = s;
3147 ( r = strchr( p, ',' ) ) != NULL;
3148 p = r + 1, i++ )
3149 ;
3150
3151 res = ch_calloc( sizeof( char ),
3152 strlen( s )
3153 + STRLENOF( "((.+),)?" )
3154 + STRLENOF( "[ ]?" ) * i
3155 + STRLENOF( "$" ) + 1 );
3156
3157 ptr = lutil_strcopy( res, "((.+),)?" );
3158 for ( i = 0, p = s;
3159 ( r = strchr( p, ',' ) ) != NULL;
3160 p = r + 1 , i++ ) {
3161 ptr = lutil_strncopy( ptr, p, r - p + 1 );
3162 ptr = lutil_strcopy( ptr, "[ ]?" );
3163
3164 if ( r[ 1 ] == ' ' ) {
3165 r++;
3166 }
3167 }
3168 ptr = lutil_strcopy( ptr, p );
3169 ptr[ 0 ] = '$';
3170 ptr++;
3171 ptr[ 0 ] = '\0';
3172
3173 return res;
3174 }
3175
3176 static char *
suffix_massage_patternize(const char * s,const char * p)3177 suffix_massage_patternize( const char *s, const char *p )
3178 {
3179 ber_len_t len;
3180 char *res, *ptr;
3181
3182 len = strlen( p );
3183
3184 if ( s[ 0 ] == '\0' ) {
3185 len++;
3186 }
3187
3188 res = ch_calloc( sizeof( char ), len + STRLENOF( "%1" ) + 1 );
3189 if ( res == NULL ) {
3190 return NULL;
3191 }
3192
3193 ptr = lutil_strcopy( res, ( p[ 0 ] == '\0' ? "%2" : "%1" ) );
3194 if ( s[ 0 ] == '\0' ) {
3195 ptr[ 0 ] = ',';
3196 ptr++;
3197 }
3198 lutil_strcopy( ptr, p );
3199
3200 return res;
3201 }
3202
3203 int
suffix_massage_config(struct rewrite_info * info,struct berval * pvnc,struct berval * nvnc,struct berval * prnc,struct berval * nrnc)3204 suffix_massage_config(
3205 struct rewrite_info *info,
3206 struct berval *pvnc,
3207 struct berval *nvnc,
3208 struct berval *prnc,
3209 struct berval *nrnc
3210 )
3211 {
3212 char *rargv[ 5 ];
3213 int line = 0;
3214
3215 rargv[ 0 ] = "rewriteEngine";
3216 rargv[ 1 ] = "on";
3217 rargv[ 2 ] = NULL;
3218 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
3219
3220 rargv[ 0 ] = "rewriteContext";
3221 rargv[ 1 ] = "default";
3222 rargv[ 2 ] = NULL;
3223 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
3224
3225 rargv[ 0 ] = "rewriteRule";
3226 rargv[ 1 ] = suffix_massage_regexize( pvnc->bv_val );
3227 rargv[ 2 ] = suffix_massage_patternize( pvnc->bv_val, prnc->bv_val );
3228 rargv[ 3 ] = ":";
3229 rargv[ 4 ] = NULL;
3230 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
3231 ch_free( rargv[ 1 ] );
3232 ch_free( rargv[ 2 ] );
3233
3234 if ( BER_BVISEMPTY( pvnc ) ) {
3235 rargv[ 0 ] = "rewriteRule";
3236 rargv[ 1 ] = "^$";
3237 rargv[ 2 ] = prnc->bv_val;
3238 rargv[ 3 ] = ":";
3239 rargv[ 4 ] = NULL;
3240 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
3241 }
3242
3243 rargv[ 0 ] = "rewriteContext";
3244 rargv[ 1 ] = "searchEntryDN";
3245 rargv[ 2 ] = NULL;
3246 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
3247
3248 rargv[ 0 ] = "rewriteRule";
3249 rargv[ 1 ] = suffix_massage_regexize( prnc->bv_val );
3250 rargv[ 2 ] = suffix_massage_patternize( prnc->bv_val, pvnc->bv_val );
3251 rargv[ 3 ] = ":";
3252 rargv[ 4 ] = NULL;
3253 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
3254 ch_free( rargv[ 1 ] );
3255 ch_free( rargv[ 2 ] );
3256
3257 if ( BER_BVISEMPTY( prnc ) ) {
3258 rargv[ 0 ] = "rewriteRule";
3259 rargv[ 1 ] = "^$";
3260 rargv[ 2 ] = pvnc->bv_val;
3261 rargv[ 3 ] = ":";
3262 rargv[ 4 ] = NULL;
3263 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
3264 }
3265
3266 /* backward compatibility */
3267 rargv[ 0 ] = "rewriteContext";
3268 rargv[ 1 ] = "searchResult";
3269 rargv[ 2 ] = "alias";
3270 rargv[ 3 ] = "searchEntryDN";
3271 rargv[ 4 ] = NULL;
3272 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
3273
3274 rargv[ 0 ] = "rewriteContext";
3275 rargv[ 1 ] = "matchedDN";
3276 rargv[ 2 ] = "alias";
3277 rargv[ 3 ] = "searchEntryDN";
3278 rargv[ 4 ] = NULL;
3279 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
3280
3281 rargv[ 0 ] = "rewriteContext";
3282 rargv[ 1 ] = "searchAttrDN";
3283 rargv[ 2 ] = "alias";
3284 rargv[ 3 ] = "searchEntryDN";
3285 rargv[ 4 ] = NULL;
3286 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
3287
3288 /* NOTE: this corresponds to #undef'ining RWM_REFERRAL_REWRITE;
3289 * see servers/slapd/overlays/rwm.h for details */
3290 rargv[ 0 ] = "rewriteContext";
3291 rargv[ 1 ] = "referralAttrDN";
3292 rargv[ 2 ] = NULL;
3293 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
3294
3295 rargv[ 0 ] = "rewriteContext";
3296 rargv[ 1 ] = "referralDN";
3297 rargv[ 2 ] = NULL;
3298 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
3299
3300 return 0;
3301 }
3302