2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2012 The OpenLDAP Foundation.
5 * Portions Copyright 2001-2003 Pierangelo Masarati.
6 * Portions Copyright 1999-2003 Howard Chu.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
18 * This work was initially developed by the Howard Chu for inclusion
19 * in OpenLDAP Software and subsequently enhanced by Pierangelo
27 #include <ac/string.h>
28 #include <ac/socket.h>
33 #include "../back-ldap/back-ldap.h"
34 #include "back-meta.h"
36 static ConfigDriver meta_back_cf_gen;
38 static int ldap_back_map_config(
40 struct ldapmap *oc_map,
41 struct ldapmap *at_map );
44 LDAP_BACK_CFG_URI = 1,
46 LDAP_BACK_CFG_ACL_AUTHCDN,
47 LDAP_BACK_CFG_ACL_PASSWD,
48 LDAP_BACK_CFG_IDASSERT_AUTHZFROM,
49 LDAP_BACK_CFG_IDASSERT_BIND,
53 LDAP_BACK_CFG_TIMEOUT,
54 LDAP_BACK_CFG_IDLE_TIMEOUT,
55 LDAP_BACK_CFG_CONN_TTL,
56 LDAP_BACK_CFG_NETWORK_TIMEOUT,
57 LDAP_BACK_CFG_VERSION,
58 LDAP_BACK_CFG_SINGLECONN,
59 LDAP_BACK_CFG_USETEMP,
60 LDAP_BACK_CFG_CONNPOOLMAX,
62 LDAP_BACK_CFG_QUARANTINE,
63 LDAP_BACK_CFG_ST_REQUEST,
65 LDAP_BACK_CFG_NOUNDEFFILTER,
67 LDAP_BACK_CFG_REWRITE,
69 LDAP_BACK_CFG_SUFFIXM,
71 LDAP_BACK_CFG_SUBTREE_EX,
72 LDAP_BACK_CFG_SUBTREE_IN,
73 LDAP_BACK_CFG_DEFAULT_T,
74 LDAP_BACK_CFG_DNCACHE_TTL,
75 LDAP_BACK_CFG_BIND_TIMEOUT,
77 LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER,
78 LDAP_BACK_CFG_PSEUDOROOTDN,
79 LDAP_BACK_CFG_PSEUDOROOTPW,
80 LDAP_BACK_CFG_NRETRIES,
81 LDAP_BACK_CFG_CLIENT_PR,
86 static ConfigTable metacfg[] = {
87 { "uri", "uri", 2, 2, 0,
88 ARG_MAGIC|LDAP_BACK_CFG_URI,
89 meta_back_cf_gen, "( OLcfgDbAt:0.14 "
91 "DESC 'URI (list) for remote DSA' "
92 "SYNTAX OMsDirectoryString "
95 { "tls", "what", 2, 0, 0,
96 ARG_MAGIC|LDAP_BACK_CFG_TLS,
97 meta_back_cf_gen, "( OLcfgDbAt:3.1 "
98 "NAME 'olcDbStartTLS' "
100 "SYNTAX OMsDirectoryString "
103 { "acl-authcDN", "DN", 2, 2, 0,
104 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_ACL_AUTHCDN,
105 meta_back_cf_gen, "( OLcfgDbAt:3.2 "
106 "NAME 'olcDbACLAuthcDn' "
107 "DESC 'Remote ACL administrative identity' "
112 /* deprecated, will be removed; aliases "acl-authcDN" */
113 { "binddn", "DN", 2, 2, 0,
114 ARG_DN|ARG_MAGIC|LDAP_BACK_CFG_ACL_AUTHCDN,
115 meta_back_cf_gen, NULL, NULL, NULL },
116 { "acl-passwd", "cred", 2, 2, 0,
117 ARG_MAGIC|LDAP_BACK_CFG_ACL_PASSWD,
118 meta_back_cf_gen, "( OLcfgDbAt:3.3 "
119 "NAME 'olcDbACLPasswd' "
120 "DESC 'Remote ACL administrative identity credentials' "
122 "SYNTAX OMsDirectoryString "
125 /* deprecated, will be removed; aliases "acl-passwd" */
126 { "bindpw", "cred", 2, 2, 0,
127 ARG_MAGIC|LDAP_BACK_CFG_ACL_PASSWD,
128 meta_back_cf_gen, NULL, NULL, NULL },
129 { "idassert-bind", "args", 2, 0, 0,
130 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND,
131 meta_back_cf_gen, "( OLcfgDbAt:3.7 "
132 "NAME 'olcDbIDAssertBind' "
133 "DESC 'Remote Identity Assertion administrative identity auth bind configuration' "
134 "SYNTAX OMsDirectoryString "
137 { "idassert-authzFrom", "authzRule", 2, 2, 0,
138 ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHZFROM,
139 meta_back_cf_gen, "( OLcfgDbAt:3.9 "
140 "NAME 'olcDbIDAssertAuthzFrom' "
141 "DESC 'Remote Identity Assertion authz rules' "
142 "EQUALITY caseIgnoreMatch "
143 "SYNTAX OMsDirectoryString "
144 "X-ORDERED 'VALUES' )",
146 { "rebind-as-user", "true|FALSE", 1, 2, 0,
147 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND,
148 meta_back_cf_gen, "( OLcfgDbAt:3.10 "
149 "NAME 'olcDbRebindAsUser' "
150 "DESC 'Rebind as user' "
154 { "chase-referrals", "true|FALSE", 2, 2, 0,
155 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE,
156 meta_back_cf_gen, "( OLcfgDbAt:3.11 "
157 "NAME 'olcDbChaseReferrals' "
158 "DESC 'Chase referrals' "
162 { "t-f-support", "true|FALSE|discover", 2, 2, 0,
163 ARG_MAGIC|LDAP_BACK_CFG_T_F,
164 meta_back_cf_gen, "( OLcfgDbAt:3.12 "
165 "NAME 'olcDbTFSupport' "
166 "DESC 'Absolute filters support' "
167 "SYNTAX OMsDirectoryString "
170 { "timeout", "timeout(list)", 2, 0, 0,
171 ARG_MAGIC|LDAP_BACK_CFG_TIMEOUT,
172 meta_back_cf_gen, "( OLcfgDbAt:3.14 "
173 "NAME 'olcDbTimeout' "
174 "DESC 'Per-operation timeouts' "
175 "SYNTAX OMsDirectoryString "
178 { "idle-timeout", "timeout", 2, 2, 0,
179 ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT,
180 meta_back_cf_gen, "( OLcfgDbAt:3.15 "
181 "NAME 'olcDbIdleTimeout' "
182 "DESC 'connection idle timeout' "
183 "SYNTAX OMsDirectoryString "
186 { "conn-ttl", "ttl", 2, 2, 0,
187 ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL,
188 meta_back_cf_gen, "( OLcfgDbAt:3.16 "
189 "NAME 'olcDbConnTtl' "
190 "DESC 'connection ttl' "
191 "SYNTAX OMsDirectoryString "
194 { "network-timeout", "timeout", 2, 2, 0,
195 ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT,
196 meta_back_cf_gen, "( OLcfgDbAt:3.17 "
197 "NAME 'olcDbNetworkTimeout' "
198 "DESC 'connection network timeout' "
199 "SYNTAX OMsDirectoryString "
202 { "protocol-version", "version", 2, 2, 0,
203 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION,
204 meta_back_cf_gen, "( OLcfgDbAt:3.18 "
205 "NAME 'olcDbProtocolVersion' "
206 "DESC 'protocol version' "
210 { "single-conn", "true|FALSE", 2, 2, 0,
211 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN,
212 meta_back_cf_gen, "( OLcfgDbAt:3.19 "
213 "NAME 'olcDbSingleConn' "
214 "DESC 'cache a single connection per identity' "
218 { "cancel", "ABANDON|ignore|exop", 2, 2, 0,
219 ARG_MAGIC|LDAP_BACK_CFG_CANCEL,
220 meta_back_cf_gen, "( OLcfgDbAt:3.20 "
221 "NAME 'olcDbCancel' "
222 "DESC 'abandon/ignore/exop operations when appropriate' "
223 "SYNTAX OMsDirectoryString "
226 { "quarantine", "retrylist", 2, 2, 0,
227 ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE,
228 meta_back_cf_gen, "( OLcfgDbAt:3.21 "
229 "NAME 'olcDbQuarantine' "
230 "DESC 'Quarantine database if connection fails and retry according to rule' "
231 "SYNTAX OMsDirectoryString "
234 { "use-temporary-conn", "true|FALSE", 2, 2, 0,
235 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_USETEMP,
236 meta_back_cf_gen, "( OLcfgDbAt:3.22 "
237 "NAME 'olcDbUseTemporaryConn' "
238 "DESC 'Use temporary connections if the cached one is busy' "
242 { "conn-pool-max", "<n>", 2, 2, 0,
243 ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX,
244 meta_back_cf_gen, "( OLcfgDbAt:3.23 "
245 "NAME 'olcDbConnectionPoolMax' "
246 "DESC 'Max size of privileged connections pool' "
250 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
251 { "session-tracking-request", "true|FALSE", 2, 2, 0,
252 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_ST_REQUEST,
253 meta_back_cf_gen, "( OLcfgDbAt:3.24 "
254 "NAME 'olcDbSessionTrackingRequest' "
255 "DESC 'Add session tracking control to proxied requests' "
259 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
260 { "norefs", "true|FALSE", 2, 2, 0,
261 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOREFS,
262 meta_back_cf_gen, "( OLcfgDbAt:3.25 "
263 "NAME 'olcDbNoRefs' "
264 "DESC 'Do not return search reference responses' "
268 { "noundeffilter", "true|FALSE", 2, 2, 0,
269 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOUNDEFFILTER,
270 meta_back_cf_gen, "( OLcfgDbAt:3.26 "
271 "NAME 'olcDbNoUndefFilter' "
272 "DESC 'Do not propagate undefined search filters' "
277 { "rewrite", "arglist", 2, 4, STRLENOF( "rewrite" ),
278 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_REWRITE,
279 meta_back_cf_gen, "( OLcfgDbAt:3.100 "
280 "NAME 'olcDbRewrite' "
281 "DESC 'DN rewriting rules' "
282 "SYNTAX OMsDirectoryString )",
284 { "suffixmassage", "virtual> <real", 3, 3, 0,
285 ARG_MAGIC|LDAP_BACK_CFG_SUFFIXM,
286 meta_back_cf_gen, "( OLcfgDbAt:3.101 "
287 "NAME 'olcDbSuffixMassage' "
288 "DESC 'Suffix rewriting rule' "
289 "SYNTAX OMsDirectoryString "
292 { "map", "attribute|objectClass> [*|<local>] *|<remote", 3, 4, 0,
293 ARG_MAGIC|LDAP_BACK_CFG_MAP,
294 meta_back_cf_gen, "( OLcfgDbAt:3.102 "
296 "DESC 'Map attribute and objectclass names' "
297 "SYNTAX OMsDirectoryString )",
300 { "subtree-exclude", "pattern", 2, 2, 0,
301 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_SUBTREE_EX,
302 meta_back_cf_gen, "( OLcfgDbAt:3.103 "
303 "NAME 'olcDbSubtreeExclude' "
304 "DESC 'DN of subtree to exclude from target' "
305 "SYNTAX OMsDirectoryString )",
307 { "subtree-include", "pattern", 2, 2, 0,
308 ARG_STRING|ARG_MAGIC|LDAP_BACK_CFG_SUBTREE_IN,
309 meta_back_cf_gen, "( OLcfgDbAt:3.104 "
310 "NAME 'olcDbSubtreeInclude' "
311 "DESC 'DN of subtree to include in target' "
312 "SYNTAX OMsDirectoryString )",
314 { "default-target", "[none|<target ID>]", 1, 2, 0,
315 ARG_MAGIC|LDAP_BACK_CFG_DEFAULT_T,
316 meta_back_cf_gen, "( OLcfgDbAt:3.105 "
317 "NAME 'olcDbDefaultTarget' "
318 "DESC 'Specify the default target' "
319 "SYNTAX OMsDirectoryString "
322 { "dncache-ttl", "ttl", 2, 2, 0,
323 ARG_MAGIC|LDAP_BACK_CFG_DNCACHE_TTL,
324 meta_back_cf_gen, "( OLcfgDbAt:3.106 "
325 "NAME 'olcDbDnCacheTtl' "
326 "DESC 'dncache ttl' "
327 "SYNTAX OMsDirectoryString "
330 { "bind-timeout", "microseconds", 2, 2, 0,
331 ARG_MAGIC|LDAP_BACK_CFG_BIND_TIMEOUT,
332 meta_back_cf_gen, "( OLcfgDbAt:3.107 "
333 "NAME 'olcDbBindTimeout' "
334 "DESC 'bind timeout' "
335 "SYNTAX OMsDirectoryString "
338 { "onerr", "CONTINUE|report|stop", 2, 2, 0,
339 ARG_MAGIC|LDAP_BACK_CFG_ONERR,
340 meta_back_cf_gen, "( OLcfgDbAt:3.108 "
342 "DESC 'error handling' "
343 "SYNTAX OMsDirectoryString "
346 { "pseudoroot-bind-defer", "TRUE|false", 2, 2, 0,
347 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER,
348 meta_back_cf_gen, "( OLcfgDbAt:3.109 "
349 "NAME 'olcDbPseudoRootBindDefer' "
350 "DESC 'error handling' "
354 { "root-bind-defer", "TRUE|false", 2, 2, 0,
355 ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER,
356 meta_back_cf_gen, NULL, NULL, NULL },
357 { "pseudorootdn", "dn", 2, 2, 0,
358 ARG_MAGIC|ARG_DN|LDAP_BACK_CFG_PSEUDOROOTDN,
359 meta_back_cf_gen, NULL, NULL, NULL },
360 { "pseudorootpw", "password", 2, 2, 0,
361 ARG_MAGIC|ARG_STRING|LDAP_BACK_CFG_PSEUDOROOTDN,
362 meta_back_cf_gen, NULL, NULL, NULL },
363 { "nretries", "NEVER|forever|<number>", 2, 2, 0,
364 ARG_MAGIC|ARG_STRING|LDAP_BACK_CFG_NRETRIES,
365 meta_back_cf_gen, "( OLcfgDbAt:3.110 "
366 "NAME 'olcDbNretries' "
367 "DESC 'retry handling' "
368 "SYNTAX OMsDirectoryString "
371 { "client-pr", "accept-unsolicited|disable|<size>", 2, 2, 0,
372 ARG_MAGIC|ARG_STRING|LDAP_BACK_CFG_CLIENT_PR,
373 meta_back_cf_gen, "( OLcfgDbAt:3.111 "
374 "NAME 'olcDbClientPr' "
375 "DESC 'PagedResults handling' "
376 "SYNTAX OMsDirectoryString "
380 { NULL, NULL, 0, 0, 0, ARG_IGNORED,
381 NULL, NULL, NULL, NULL }
384 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
385 #define ST_ATTR "$ olcDbSessionTrackingRequest "
388 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
390 #define TARGET_ATTRS \
392 "$ olcDbChaseReferrals " \
394 "$ olcDbDefaultTarget " \
395 "$ olcDbIdleTimeout " \
396 "$ olcDbNetworkTimeout " \
398 "$ olcDbNoUndefFilter " \
400 "$ olcDbProtocolVersion " \
404 static ConfigOCs metaocs[] = {
406 "NAME 'olcMetaConfig' "
407 "DESC 'Meta backend configuration' "
408 "SUP olcDatabaseConfig "
409 "MAY ( olcDbConnTtl "
412 "$ olcDbPseudoRootBindDefer "
414 "$ olcDbRebindAsUser "
416 "$ olcDbUseTemporaryConn "
417 "$ olcDbConnectionPoolMax "
419 /* defaults, may be overridden per-target */
422 Cft_Database, metacfg},
424 "NAME 'olcMetaTarget' "
425 "DESC 'Meta target configuration' "
427 "MAY ( olcDbACLAuthcDn "
429 "$ olcDbBindTimeout "
430 "$ olcDbIDAssertAuthzFrom "
431 "$ olcDbIDAssertBind "
434 "$ olcDbSubtreeExclude "
435 "$ olcDbSubtreeInclude "
436 "$ olcDbSuffixMassage "
440 /* defaults may be inherited */
443 Cft_Misc, metacfg, NULL /* meta_ldadd */},
448 meta_back_new_target(
456 mt = ch_calloc( sizeof( metatarget_t ), 1 );
458 mt->mt_rwmap.rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
459 if ( mt->mt_rwmap.rwm_rw == NULL ) {
465 * the filter rewrite as a string must be disabled
466 * by default; it can be re-enabled by adding rules;
467 * this creates an empty rewriteContext
469 rargv[ 0 ] = "rewriteContext";
470 rargv[ 1 ] = "searchFilter";
472 rewrite_parse( mt->mt_rwmap.rwm_rw, "<suffix massage>", 1, 2, rargv );
474 rargv[ 0 ] = "rewriteContext";
475 rargv[ 1 ] = "default";
477 rewrite_parse( mt->mt_rwmap.rwm_rw, "<suffix massage>", 1, 2, rargv );
479 ldap_pvt_thread_mutex_init( &mt->mt_uri_mutex );
481 mt->mt_idassert_mode = LDAP_BACK_IDASSERT_LEGACY;
482 mt->mt_idassert_authmethod = LDAP_AUTH_NONE;
483 mt->mt_idassert_tls = SB_TLS_DEFAULT;
485 /* by default, use proxyAuthz control on each operation */
486 mt->mt_idassert_flags = LDAP_BACK_AUTH_PRESCRIPTIVE;
494 meta_subtree_destroy( metasubtree_t *ms )
497 meta_subtree_destroy( ms->ms_next );
500 switch ( ms->ms_type ) {
501 case META_ST_SUBTREE:
502 case META_ST_SUBORDINATE:
503 ber_memfree( ms->ms_dn.bv_val );
507 regfree( &ms->ms_regex );
508 ch_free( ms->ms_regex_pattern );
525 meta_st_t type = META_ST_SUBTREE;
527 struct berval ndn = BER_BVNULL;
528 metasubtree_t *ms = NULL;
530 if ( c->type == LDAP_BACK_CFG_SUBTREE_EX ) {
531 if ( mt->mt_subtree && !mt->mt_subtree_exclude ) {
532 snprintf( c->cr_msg, sizeof(c->cr_msg),
533 "\"subtree-exclude\" incompatible with previous \"subtree-include\" directives" );
537 mt->mt_subtree_exclude = 1;
540 if ( mt->mt_subtree && mt->mt_subtree_exclude ) {
541 snprintf( c->cr_msg, sizeof(c->cr_msg),
542 "\"subtree-include\" incompatible with previous \"subtree-exclude\" directives" );
547 pattern = c->argv[1];
548 if ( strncasecmp( pattern, "dn", STRLENOF( "dn" ) ) == 0 ) {
551 pattern = &pattern[STRLENOF( "dn")];
553 if ( pattern[0] == '.' ) {
556 if ( strncasecmp( style, "subtree", STRLENOF( "subtree" ) ) == 0 ) {
557 type = META_ST_SUBTREE;
558 pattern = &style[STRLENOF( "subtree" )];
560 } else if ( strncasecmp( style, "children", STRLENOF( "children" ) ) == 0 ) {
561 type = META_ST_SUBORDINATE;
562 pattern = &style[STRLENOF( "children" )];
564 } else if ( strncasecmp( style, "sub", STRLENOF( "sub" ) ) == 0 ) {
565 type = META_ST_SUBTREE;
566 pattern = &style[STRLENOF( "sub" )];
568 } else if ( strncasecmp( style, "regex", STRLENOF( "regex" ) ) == 0 ) {
569 type = META_ST_REGEX;
570 pattern = &style[STRLENOF( "regex" )];
573 snprintf( c->cr_msg, sizeof(c->cr_msg), "unknown style in \"dn.<style>\"" );
578 if ( pattern[0] != ':' ) {
579 snprintf( c->cr_msg, sizeof(c->cr_msg), "missing colon after \"dn.<style>\"" );
586 case META_ST_SUBTREE:
587 case META_ST_SUBORDINATE: {
590 ber_str2bv( pattern, 0, 0, &dn );
591 if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL )
594 snprintf( c->cr_msg, sizeof(c->cr_msg), "DN=\"%s\" is invalid", pattern );
598 if ( !dnIsSuffix( &ndn, &mt->mt_nsuffix ) ) {
599 snprintf( c->cr_msg, sizeof(c->cr_msg),
600 "DN=\"%s\" is not a subtree of target \"%s\"",
601 pattern, mt->mt_nsuffix.bv_val );
602 ber_memfree( ndn.bv_val );
608 /* silence warnings */
612 ms = ch_calloc( sizeof( metasubtree_t ), 1 );
615 switch ( ms->ms_type ) {
616 case META_ST_SUBTREE:
617 case META_ST_SUBORDINATE:
621 case META_ST_REGEX: {
624 rc = regcomp( &ms->ms_regex, pattern, REG_EXTENDED|REG_ICASE );
626 char regerr[ SLAP_TEXT_BUFLEN ];
628 regerror( rc, &ms->ms_regex, regerr, sizeof(regerr) );
630 snprintf( c->cr_msg, sizeof( c->cr_msg ),
631 "regular expression \"%s\" bad because of %s",
636 ms->ms_regex_pattern = ch_strdup( pattern );
640 if ( mt->mt_subtree == NULL ) {
646 for ( msp = &mt->mt_subtree; *msp; ) {
647 switch ( ms->ms_type ) {
648 case META_ST_SUBTREE:
649 switch ( (*msp)->ms_type ) {
650 case META_ST_SUBTREE:
651 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
652 metasubtree_t *tmp = *msp;
653 Debug( LDAP_DEBUG_CONFIG,
654 "%s: previous rule \"dn.subtree:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n",
655 c->log, pattern, (*msp)->ms_dn.bv_val );
656 *msp = (*msp)->ms_next;
658 meta_subtree_destroy( tmp );
661 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) ) {
662 Debug( LDAP_DEBUG_CONFIG,
663 "%s: previous rule \"dn.subtree:%s\" contains rule \"dn.subtree:%s\" (ignored)\n",
664 c->log, (*msp)->ms_dn.bv_val, pattern );
665 meta_subtree_destroy( ms );
671 case META_ST_SUBORDINATE:
672 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
673 metasubtree_t *tmp = *msp;
674 Debug( LDAP_DEBUG_CONFIG,
675 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n",
676 c->log, pattern, (*msp)->ms_dn.bv_val );
677 *msp = (*msp)->ms_next;
679 meta_subtree_destroy( tmp );
682 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) && ms->ms_dn.bv_len > (*msp)->ms_dn.bv_len ) {
683 Debug( LDAP_DEBUG_CONFIG,
684 "%s: previous rule \"dn.children:%s\" contains rule \"dn.subtree:%s\" (ignored)\n",
685 c->log, (*msp)->ms_dn.bv_val, pattern );
686 meta_subtree_destroy( ms );
693 if ( regexec( &(*msp)->ms_regex, ms->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) {
694 Debug( LDAP_DEBUG_CONFIG,
695 "%s: previous rule \"dn.regex:%s\" may contain rule \"dn.subtree:%s\"\n",
696 c->log, (*msp)->ms_regex_pattern, ms->ms_dn.bv_val );
702 case META_ST_SUBORDINATE:
703 switch ( (*msp)->ms_type ) {
704 case META_ST_SUBTREE:
705 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
706 metasubtree_t *tmp = *msp;
707 Debug( LDAP_DEBUG_CONFIG,
708 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n",
709 c->log, pattern, (*msp)->ms_dn.bv_val );
710 *msp = (*msp)->ms_next;
712 meta_subtree_destroy( tmp );
715 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) && ms->ms_dn.bv_len > (*msp)->ms_dn.bv_len ) {
716 Debug( LDAP_DEBUG_CONFIG,
717 "%s: previous rule \"dn.children:%s\" contains rule \"dn.subtree:%s\" (ignored)\n",
718 c->log, (*msp)->ms_dn.bv_val, pattern );
719 meta_subtree_destroy( ms );
725 case META_ST_SUBORDINATE:
726 if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
727 metasubtree_t *tmp = *msp;
728 Debug( LDAP_DEBUG_CONFIG,
729 "%s: previous rule \"dn.children:%s\" is contained in rule \"dn.children:%s\" (replaced)\n",
730 c->log, pattern, (*msp)->ms_dn.bv_val );
731 *msp = (*msp)->ms_next;
733 meta_subtree_destroy( tmp );
736 } else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) ) {
737 Debug( LDAP_DEBUG_CONFIG,
738 "%s: previous rule \"dn.children:%s\" contains rule \"dn.children:%s\" (ignored)\n",
739 c->log, (*msp)->ms_dn.bv_val, pattern );
740 meta_subtree_destroy( ms );
747 if ( regexec( &(*msp)->ms_regex, ms->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) {
748 Debug( LDAP_DEBUG_CONFIG,
749 "%s: previous rule \"dn.regex:%s\" may contain rule \"dn.subtree:%s\"\n",
750 c->log, (*msp)->ms_regex_pattern, ms->ms_dn.bv_val );
757 switch ( (*msp)->ms_type ) {
758 case META_ST_SUBTREE:
759 case META_ST_SUBORDINATE:
760 if ( regexec( &ms->ms_regex, (*msp)->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) {
761 Debug( LDAP_DEBUG_CONFIG,
762 "%s: previous rule \"dn.subtree:%s\" may be contained in rule \"dn.regex:%s\"\n",
763 c->log, (*msp)->ms_dn.bv_val, ms->ms_regex_pattern );
768 /* no check possible */
774 msp = &(*msp)->ms_next;
783 static slap_verbmasks idassert_mode[] = {
784 { BER_BVC("self"), LDAP_BACK_IDASSERT_SELF },
785 { BER_BVC("anonymous"), LDAP_BACK_IDASSERT_ANONYMOUS },
786 { BER_BVC("none"), LDAP_BACK_IDASSERT_NOASSERT },
787 { BER_BVC("legacy"), LDAP_BACK_IDASSERT_LEGACY },
791 static slap_verbmasks tls_mode[] = {
792 { BER_BVC( "propagate" ), LDAP_BACK_F_TLS_PROPAGATE_MASK },
793 { BER_BVC( "try-propagate" ), LDAP_BACK_F_PROPAGATE_TLS },
794 { BER_BVC( "start" ), LDAP_BACK_F_TLS_USE_MASK },
795 { BER_BVC( "try-start" ), LDAP_BACK_F_USE_TLS },
796 { BER_BVC( "ldaps" ), LDAP_BACK_F_TLS_LDAPS },
797 { BER_BVC( "none" ), LDAP_BACK_F_NONE },
801 static slap_verbmasks t_f_mode[] = {
802 { BER_BVC( "yes" ), LDAP_BACK_F_T_F },
803 { BER_BVC( "discover" ), LDAP_BACK_F_T_F_DISCOVER },
804 { BER_BVC( "no" ), LDAP_BACK_F_NONE },
808 static slap_verbmasks cancel_mode[] = {
809 { BER_BVC( "ignore" ), LDAP_BACK_F_CANCEL_IGNORE },
810 { BER_BVC( "exop" ), LDAP_BACK_F_CANCEL_EXOP },
811 { BER_BVC( "exop-discover" ), LDAP_BACK_F_CANCEL_EXOP_DISCOVER },
812 { BER_BVC( "abandon" ), LDAP_BACK_F_CANCEL_ABANDON },
816 static slap_verbmasks onerr_mode[] = {
817 { BER_BVC( "stop" ), META_BACK_F_ONERR_STOP },
818 { BER_BVC( "report" ), META_BACK_F_ONERR_REPORT },
819 { BER_BVC( "continue" ), LDAP_BACK_F_NONE },
823 /* see enum in slap.h */
824 static slap_cf_aux_table timeout_table[] = {
825 { BER_BVC("bind="), SLAP_OP_BIND * sizeof( time_t ), 'u', 0, NULL },
826 /* unbind makes no sense */
827 { BER_BVC("add="), SLAP_OP_ADD * sizeof( time_t ), 'u', 0, NULL },
828 { BER_BVC("delete="), SLAP_OP_DELETE * sizeof( time_t ), 'u', 0, NULL },
829 { BER_BVC("modrdn="), SLAP_OP_MODRDN * sizeof( time_t ), 'u', 0, NULL },
830 { BER_BVC("modify="), SLAP_OP_MODIFY * sizeof( time_t ), 'u', 0, NULL },
831 { BER_BVC("compare="), SLAP_OP_COMPARE * sizeof( time_t ), 'u', 0, NULL },
832 { BER_BVC("search="), SLAP_OP_SEARCH * sizeof( time_t ), 'u', 0, NULL },
833 /* abandon makes little sense */
834 #if 0 /* not implemented yet */
835 { BER_BVC("extended="), SLAP_OP_EXTENDED * sizeof( time_t ), 'u', 0, NULL },
837 { BER_BVNULL, 0, 0, 0, NULL }
841 meta_back_cf_gen( ConfigArgs *c )
843 metainfo_t *mi = ( metainfo_t * )c->be->be_private;
846 assert( mi != NULL );
848 if ( c->op == SLAP_CONFIG_EMIT ) {
850 } else if ( c->op == LDAP_MOD_DELETE ) {
855 case LDAP_BACK_CFG_URI: {
864 if ( c->be->be_nsuffix == NULL ) {
865 snprintf( c->cr_msg, sizeof( c->cr_msg ),
866 "the suffix must be defined before any target" );
867 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
871 i = mi->mi_ntargets++;
873 mi->mi_targets = ( metatarget_t ** )ch_realloc( mi->mi_targets,
874 sizeof( metatarget_t * ) * mi->mi_ntargets );
875 if ( mi->mi_targets == NULL ) {
876 snprintf( c->cr_msg, sizeof( c->cr_msg ),
877 "out of memory while storing server name"
878 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
880 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
884 if ( meta_back_new_target( &mi->mi_targets[ i ] ) != 0 ) {
885 snprintf( c->cr_msg, sizeof( c->cr_msg ),
886 "unable to init server"
887 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
889 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
893 mt = mi->mi_targets[ i ];
895 mt->mt_rebind_f = mi->mi_rebind_f;
896 mt->mt_urllist_f = mi->mi_urllist_f;
897 mt->mt_urllist_p = mt;
899 mt->mt_nretries = mi->mi_nretries;
900 mt->mt_quarantine = mi->mi_quarantine;
901 if ( META_BACK_QUARANTINE( mi ) ) {
902 ldap_pvt_thread_mutex_init( &mt->mt_quarantine_mutex );
904 mt->mt_flags = mi->mi_flags;
905 mt->mt_version = mi->mi_version;
906 #ifdef SLAPD_META_CLIENT_PR
907 mt->mt_ps = mi->mi_ps;
908 #endif /* SLAPD_META_CLIENT_PR */
909 mt->mt_network_timeout = mi->mi_network_timeout;
910 mt->mt_bind_timeout = mi->mi_bind_timeout;
911 for ( j = 0; j < SLAP_OP_LAST; j++ ) {
912 mt->mt_timeout[ j ] = mi->mi_timeout[ j ];
915 for ( j = 1; j < c->argc; j++ ) {
916 char **tmpuris = ldap_str2charray( c->argv[ j ], "\t" );
918 if ( tmpuris == NULL ) {
919 snprintf( c->cr_msg, sizeof( c->cr_msg ),
920 "unable to parse URIs #%d"
921 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
923 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
931 ldap_charray_merge( &uris, tmpuris );
932 ldap_charray_free( tmpuris );
936 for ( j = 0; uris[ j ] != NULL; j++ ) {
942 if ( ldap_url_parselist_ext( &ludp, uris[ j ], "\t",
943 LDAP_PVT_URL_PARSE_NONE ) != LDAP_SUCCESS
944 || ludp->lud_next != NULL )
946 snprintf( c->cr_msg, sizeof( c->cr_msg ),
947 "unable to parse URI #%d"
948 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
950 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
951 ldap_charray_free( uris );
958 * uri MUST have the <dn> part!
960 if ( ludp->lud_dn == NULL ) {
961 snprintf( c->cr_msg, sizeof( c->cr_msg ),
962 "missing <naming context> "
963 " in \"%s <protocol>://<server>[:port]/<naming context>\"",
965 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
966 ldap_free_urllist( ludp );
967 ldap_charray_free( uris );
972 * copies and stores uri and suffix
974 ber_str2bv( ludp->lud_dn, 0, 0, &dn );
975 rc = dnPrettyNormal( NULL, &dn, &mt->mt_psuffix,
976 &mt->mt_nsuffix, NULL );
977 if ( rc != LDAP_SUCCESS ) {
978 snprintf( c->cr_msg, sizeof( c->cr_msg ),
979 "target DN is invalid \"%s\"",
981 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
982 ldap_free_urllist( ludp );
983 ldap_charray_free( uris );
987 ludp->lud_dn[ 0 ] = '\0';
989 switch ( ludp->lud_scope ) {
990 case LDAP_SCOPE_DEFAULT:
991 mt->mt_scope = LDAP_SCOPE_SUBTREE;
994 case LDAP_SCOPE_SUBTREE:
995 case LDAP_SCOPE_SUBORDINATE:
996 mt->mt_scope = ludp->lud_scope;
1000 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1001 "invalid scope for target \"%s\"",
1003 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1004 ldap_free_urllist( ludp );
1005 ldap_charray_free( uris );
1010 /* check all, to apply the scope check on the first one */
1011 if ( ludp->lud_dn != NULL && ludp->lud_dn[ 0 ] != '\0' ) {
1012 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1013 "multiple URIs must have no DN part" );
1014 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1015 ldap_free_urllist( ludp );
1016 ldap_charray_free( uris );
1022 tmpuri = ldap_url_list2urls( ludp );
1023 ldap_free_urllist( ludp );
1024 if ( tmpuri == NULL ) {
1025 snprintf( c->cr_msg, sizeof( c->cr_msg ), "no memory?" );
1026 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1027 ldap_charray_free( uris );
1030 ldap_memfree( uris[ j ] );
1034 mt->mt_uri = ldap_charray2str( uris, " " );
1035 ldap_charray_free( uris );
1036 if ( mt->mt_uri == NULL) {
1037 snprintf( c->cr_msg, sizeof( c->cr_msg ), "no memory?" );
1038 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1043 * uri MUST be a branch of suffix!
1045 for ( j = 0; !BER_BVISNULL( &c->be->be_nsuffix[ j ] ); j++ ) {
1046 if ( dnIsSuffix( &mt->mt_nsuffix, &c->be->be_nsuffix[ j ] ) ) {
1051 if ( BER_BVISNULL( &c->be->be_nsuffix[ j ] ) ) {
1052 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1053 "<naming context> of URI must be within the naming context of this database." );
1054 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1058 case LDAP_BACK_CFG_SUBTREE_EX:
1059 case LDAP_BACK_CFG_SUBTREE_IN:
1060 /* subtree-exclude */
1061 i = mi->mi_ntargets - 1;
1064 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1065 "need \"uri\" directive first" );
1066 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1070 if ( meta_subtree_config( mi->mi_targets[ i ], c )) {
1071 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1076 case LDAP_BACK_CFG_DEFAULT_T:
1077 /* default target directive */
1078 i = mi->mi_ntargets - 1;
1080 if ( c->argc == 1 ) {
1082 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1083 "\"%s\" alone must be inside a \"uri\" directive",
1085 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1088 mi->mi_defaulttarget = i;
1091 if ( strcasecmp( c->argv[ 1 ], "none" ) == 0 ) {
1093 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1094 "\"%s none\" should go before uri definitions",
1096 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1098 mi->mi_defaulttarget = META_DEFAULT_TARGET_NONE;
1102 if ( lutil_atoi( &mi->mi_defaulttarget, c->argv[ 1 ] ) != 0
1103 || mi->mi_defaulttarget < 0
1104 || mi->mi_defaulttarget >= i - 1 )
1106 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1107 "illegal target number %d",
1108 mi->mi_defaulttarget );
1109 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1116 case LDAP_BACK_CFG_DNCACHE_TTL:
1117 /* ttl of dn cache */
1118 if ( strcasecmp( c->argv[ 1 ], "forever" ) == 0 ) {
1119 mi->mi_cache.ttl = META_DNCACHE_FOREVER;
1121 } else if ( strcasecmp( c->argv[ 1 ], "disabled" ) == 0 ) {
1122 mi->mi_cache.ttl = META_DNCACHE_DISABLED;
1127 if ( lutil_parse_time( c->argv[ 1 ], &t ) != 0 ) {
1128 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1129 "unable to parse dncache ttl \"%s\"",
1131 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1134 mi->mi_cache.ttl = (time_t)t;
1138 case LDAP_BACK_CFG_NETWORK_TIMEOUT: {
1139 /* network timeout when connecting to ldap servers */
1141 time_t *tp = mi->mi_ntargets ?
1142 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_network_timeout
1143 : &mi->mi_network_timeout;
1145 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) {
1146 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1147 "unable to parse network timeout \"%s\"",
1149 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1156 case LDAP_BACK_CFG_IDLE_TIMEOUT: {
1157 /* idle timeout when connecting to ldap servers */
1160 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) {
1161 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1162 "unable to parse idle timeout \"%s\"",
1164 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1168 mi->mi_idle_timeout = (time_t)t;
1171 case LDAP_BACK_CFG_CONN_TTL: {
1175 if ( lutil_parse_time( c->argv[ 1 ], &t ) ) {
1176 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1177 "unable to parse conn ttl \"%s\"",
1179 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1183 mi->mi_conn_ttl = (time_t)t;
1186 case LDAP_BACK_CFG_BIND_TIMEOUT: {
1187 /* bind timeout when connecting to ldap servers */
1189 struct timeval *tp = mi->mi_ntargets ?
1190 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_bind_timeout
1191 : &mi->mi_bind_timeout;
1193 if ( lutil_atoul( &t, c->argv[ 1 ] ) != 0 ) {
1194 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1195 "unable to parse bind timeout \"%s\"",
1197 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1202 tp->tv_sec = t/1000000;
1203 tp->tv_usec = t%1000000;
1206 case LDAP_BACK_CFG_ACL_AUTHCDN:
1207 /* name to use for meta_back_group */
1209 i = mi->mi_ntargets - 1;
1211 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1212 "need \"uri\" directive first" );
1213 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1217 if ( strcasecmp( c->argv[ 0 ], "binddn" ) == 0 ) {
1218 Debug( LDAP_DEBUG_ANY, "%s: "
1219 "\"binddn\" statement is deprecated; "
1220 "use \"acl-authcDN\" instead\n",
1222 /* FIXME: some day we'll need to throw an error */
1225 ber_memfree_x( c->value_dn.bv_val, NULL );
1226 mi->mi_targets[ i ]->mt_binddn = c->value_ndn;
1227 BER_BVZERO( &c->value_dn );
1228 BER_BVZERO( &c->value_ndn );
1231 case LDAP_BACK_CFG_ACL_PASSWD:
1232 /* password to use for meta_back_group */
1233 i = mi->mi_ntargets - 1;
1236 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1237 "need \"uri\" directive first" );
1238 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1242 if ( strcasecmp( c->argv[ 0 ], "bindpw" ) == 0 ) {
1243 Debug( LDAP_DEBUG_ANY, "%s "
1244 "\"bindpw\" statement is deprecated; "
1245 "use \"acl-passwd\" instead\n",
1247 /* FIXME: some day we'll need to throw an error */
1250 ber_str2bv( c->argv[ 1 ], 0L, 1, &mi->mi_targets[ i ]->mt_bindpw );
1253 case LDAP_BACK_CFG_REBIND: {
1254 /* save bind creds for referral rebinds? */
1255 unsigned *flagsp = mi->mi_ntargets ?
1256 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
1259 if ( c->argc == 1 || c->value_int ) {
1260 *flagsp |= LDAP_BACK_F_SAVECRED;
1262 *flagsp &= ~LDAP_BACK_F_SAVECRED;
1266 case LDAP_BACK_CFG_CHASE: {
1267 unsigned *flagsp = mi->mi_ntargets ?
1268 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
1271 if ( c->argc == 1 || c->value_int ) {
1272 *flagsp |= LDAP_BACK_F_CHASE_REFERRALS;
1274 *flagsp &= ~LDAP_BACK_F_CHASE_REFERRALS;
1278 case LDAP_BACK_CFG_TLS: {
1279 unsigned *flagsp = mi->mi_ntargets ?
1280 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
1283 i = verb_to_mask( c->argv[1], tls_mode );
1284 if ( BER_BVISNULL( &tls_mode[i].word ) ) {
1285 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1286 "%s unknown argument \"%s\"",
1287 c->argv[0], c->argv[1] );
1288 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1292 if ( c->argc > 2 ) {
1293 metatarget_t *mt = NULL;
1295 if ( mi->mi_ntargets - 1 < 0 ) {
1296 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1297 "need \"uri\" directive first" );
1298 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1302 mt = mi->mi_targets[ mi->mi_ntargets - 1 ];
1304 for ( i = 2; i < c->argc; i++ ) {
1305 if ( bindconf_tls_parse( c->argv[i], &mt->mt_tls ))
1308 bindconf_tls_defaults( &mt->mt_tls );
1312 case LDAP_BACK_CFG_T_F: {
1313 unsigned *flagsp = mi->mi_ntargets ?
1314 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
1318 i = verb_to_mask( c->argv[1], t_f_mode );
1319 if ( BER_BVISNULL( &t_f_mode[i].word ) ) {
1320 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1321 "%s unknown argument \"%s\"",
1322 c->argv[0], c->argv[1] );
1323 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1326 mask = t_f_mode[i].mask;
1328 *flagsp &= ~LDAP_BACK_F_T_F_MASK2;
1332 case LDAP_BACK_CFG_ONERR: {
1336 i = verb_to_mask( c->argv[1], onerr_mode );
1337 if ( BER_BVISNULL( &onerr_mode[i].word ) ) {
1338 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1339 "%s unknown argument \"%s\"",
1340 c->argv[0], c->argv[1] );
1341 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1344 mask = onerr_mode[i].mask;
1346 mi->mi_flags &= ~META_BACK_F_ONERR_MASK;
1347 mi->mi_flags |= mask;
1350 case LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER:
1352 if ( c->argc == 1 || c->value_int ) {
1353 mi->mi_flags |= META_BACK_F_DEFER_ROOTDN_BIND;
1355 mi->mi_flags &= ~META_BACK_F_DEFER_ROOTDN_BIND;
1359 case LDAP_BACK_CFG_SINGLECONN:
1361 if ( mi->mi_ntargets > 0 ) {
1362 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1363 "\"%s\" must appear before target definitions",
1365 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1368 if ( c->value_int ) {
1369 mi->mi_flags |= LDAP_BACK_F_SINGLECONN;
1371 mi->mi_flags &= ~LDAP_BACK_F_SINGLECONN;
1375 case LDAP_BACK_CFG_USETEMP:
1376 /* use-temporaries? */
1377 if ( mi->mi_ntargets > 0 ) {
1378 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1379 "\"%s\" must appear before target definitions",
1381 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1384 if ( c->value_int ) {
1385 mi->mi_flags |= LDAP_BACK_F_USE_TEMPORARIES;
1387 mi->mi_flags &= ~LDAP_BACK_F_USE_TEMPORARIES;
1391 case LDAP_BACK_CFG_CONNPOOLMAX:
1392 /* privileged connections pool max size ? */
1393 if ( mi->mi_ntargets > 0 ) {
1394 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1395 "\"%s\" must appear before target definitions",
1397 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1401 if ( c->value_int < LDAP_BACK_CONN_PRIV_MIN
1402 || c->value_int > LDAP_BACK_CONN_PRIV_MAX )
1404 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1405 "invalid max size " "of privileged "
1406 "connections pool \"%s\" "
1407 "in \"conn-pool-max <n> "
1408 "(must be between %d and %d)\"",
1410 LDAP_BACK_CONN_PRIV_MIN,
1411 LDAP_BACK_CONN_PRIV_MAX );
1412 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1415 mi->mi_conn_priv_max = c->value_int;
1418 case LDAP_BACK_CFG_CANCEL: {
1419 unsigned *flagsp = mi->mi_ntargets ?
1420 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
1424 i = verb_to_mask( c->argv[1], cancel_mode );
1425 if ( BER_BVISNULL( &cancel_mode[i].word ) ) {
1426 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1427 "%s unknown argument \"%s\"",
1428 c->argv[0], c->argv[1] );
1429 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1432 mask = t_f_mode[i].mask;
1434 *flagsp &= ~LDAP_BACK_F_CANCEL_MASK2;
1438 case LDAP_BACK_CFG_TIMEOUT: {
1439 time_t *tv = mi->mi_ntargets ?
1440 mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_timeout
1443 for ( i = 1; i < c->argc; i++ ) {
1444 if ( isdigit( (unsigned char) c->argv[ i ][ 0 ] ) ) {
1448 if ( lutil_atoux( &u, c->argv[ i ], 0 ) != 0 ) {
1449 snprintf( c->cr_msg, sizeof( c->cr_msg),
1450 "unable to parse timeout \"%s\"",
1452 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1456 for ( j = 0; j < SLAP_OP_LAST; j++ ) {
1463 if ( slap_cf_aux_table_parse( c->argv[ i ], tv, timeout_table, "slapd-meta timeout" ) ) {
1464 snprintf( c->cr_msg, sizeof( c->cr_msg),
1465 "unable to parse timeout \"%s\"",
1467 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1473 case LDAP_BACK_CFG_PSEUDOROOTDN:
1474 /* name to use as pseudo-root dn */
1475 i = mi->mi_ntargets - 1;
1478 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1479 "need \"uri\" directive first" );
1480 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1485 * exact replacement:
1488 idassert-bind bindmethod=simple
1489 binddn=<pseudorootdn>
1490 credentials=<pseudorootpw>
1492 flags=non-prescriptive
1493 idassert-authzFrom "dn:<rootdn>"
1495 * so that only when authc'd as <rootdn> the proxying occurs
1496 * rebinding as the <pseudorootdn> without proxyAuthz.
1499 Debug( LDAP_DEBUG_ANY,
1500 "%s: \"pseudorootdn\", \"pseudorootpw\" are no longer supported; "
1501 "use \"idassert-bind\" and \"idassert-authzFrom\" instead.\n",
1505 char binddn[ SLAP_TEXT_BUFLEN ];
1508 "bindmethod=simple",
1511 "flags=non-prescriptive",
1520 if ( BER_BVISNULL( &c->be->be_rootndn ) ) {
1521 Debug( LDAP_DEBUG_ANY, "%s: \"pseudorootpw\": \"rootdn\" must be defined first.\n",
1526 if ( sizeof( binddn ) <= (unsigned) snprintf( binddn,
1527 sizeof( binddn ), "binddn=%s", c->argv[ 1 ] ))
1529 Debug( LDAP_DEBUG_ANY, "%s: \"pseudorootdn\" too long.\n",
1533 cargv[ 2 ] = binddn;
1539 rc = mi->mi_ldap_extra->idassert_parse( c, &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert );
1545 if ( mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authz != NULL ) {
1546 Debug( LDAP_DEBUG_ANY, "%s: \"idassert-authzFrom\" already defined (discarded).\n",
1548 ber_bvarray_free( mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authz );
1549 mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authz = NULL;
1552 assert( !BER_BVISNULL( &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authcDN ) );
1554 bv.bv_len = STRLENOF( "dn:" ) + c->be->be_rootndn.bv_len;
1555 bv.bv_val = ber_memalloc( bv.bv_len + 1 );
1556 AC_MEMCPY( bv.bv_val, "dn:", STRLENOF( "dn:" ) );
1557 AC_MEMCPY( &bv.bv_val[ STRLENOF( "dn:" ) ], c->be->be_rootndn.bv_val, c->be->be_rootndn.bv_len + 1 );
1559 ber_bvarray_add( &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert_authz, &bv );
1566 case LDAP_BACK_CFG_PSEUDOROOTPW:
1567 /* password to use as pseudo-root */
1568 i = mi->mi_ntargets - 1;
1571 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1572 "need \"uri\" directive first" );
1573 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1577 Debug( LDAP_DEBUG_ANY,
1578 "%s: \"pseudorootdn\", \"pseudorootpw\" are no longer supported; "
1579 "use \"idassert-bind\" and \"idassert-authzFrom\" instead.\n",
1582 if ( BER_BVISNULL( &mi->mi_targets[ i ]->mt_idassert_authcDN ) ) {
1583 Debug( LDAP_DEBUG_ANY, "%s: \"pseudorootpw\": \"pseudorootdn\" must be defined first.\n",
1588 if ( !BER_BVISNULL( &mi->mi_targets[ i ]->mt_idassert_passwd ) ) {
1589 memset( mi->mi_targets[ i ]->mt_idassert_passwd.bv_val, 0,
1590 mi->mi_targets[ i ]->mt_idassert_passwd.bv_len );
1591 ber_memfree( mi->mi_targets[ i ]->mt_idassert_passwd.bv_val );
1593 ber_str2bv( c->argv[ 1 ], 0, 1, &mi->mi_targets[ i ]->mt_idassert_passwd );
1595 case LDAP_BACK_CFG_IDASSERT_BIND:
1597 if ( mi->mi_ntargets == 0 ) {
1598 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1599 "need \"uri\" directive first" );
1600 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1604 rc = mi->mi_ldap_extra->idassert_parse( c, &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert );
1607 case LDAP_BACK_CFG_IDASSERT_AUTHZFROM:
1608 /* idassert-authzFrom */
1609 if ( mi->mi_ntargets == 0 ) {
1610 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1611 "need \"uri\" directive first" );
1612 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1616 rc = mi->mi_ldap_extra->idassert_authzfrom_parse( c, &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_idassert );
1619 case LDAP_BACK_CFG_QUARANTINE: {
1621 slap_retry_info_t *ri = mi->mi_ntargets ?
1622 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_quarantine
1623 : &mi->mi_quarantine;
1625 if ( ( mi->mi_ntargets == 0 && META_BACK_QUARANTINE( mi ) )
1626 || ( mi->mi_ntargets > 0 && META_BACK_TGT_QUARANTINE( mi->mi_targets[ mi->mi_ntargets - 1 ] ) ) )
1628 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1629 "quarantine already defined" );
1630 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1634 if ( ri != &mi->mi_quarantine ) {
1635 ri->ri_interval = NULL;
1639 if ( mi->mi_ntargets > 0 && !META_BACK_QUARANTINE( mi ) ) {
1640 ldap_pvt_thread_mutex_init( &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_quarantine_mutex );
1643 if ( mi->mi_ldap_extra->retry_info_parse( c->argv[ 1 ], ri, c->cr_msg, sizeof( c->cr_msg ) ) ) {
1644 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1648 if ( mi->mi_ntargets == 0 ) {
1649 mi->mi_flags |= LDAP_BACK_F_QUARANTINE;
1652 mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags |= LDAP_BACK_F_QUARANTINE;
1656 #ifdef SLAP_CONTROL_X_SESSION_TRACKING
1657 case LDAP_BACK_CFG_ST_REQUEST: {
1658 /* session tracking request */
1659 unsigned *flagsp = mi->mi_ntargets ?
1660 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
1663 if ( c->value_int ) {
1664 *flagsp |= LDAP_BACK_F_ST_REQUEST;
1666 *flagsp &= ~LDAP_BACK_F_ST_REQUEST;
1669 #endif /* SLAP_CONTROL_X_SESSION_TRACKING */
1671 case LDAP_BACK_CFG_SUFFIXM: {
1674 struct berval dn, nvnc, pvnc, nrnc, prnc;
1677 i = mi->mi_ntargets - 1;
1679 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1680 "need \"uri\" directive first" );
1681 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1688 * suffixmassage <suffix> <massaged suffix>
1690 * the <suffix> field must be defined as a valid suffix
1691 * (or suffixAlias?) for the current database;
1692 * the <massaged suffix> shouldn't have already been
1693 * defined as a valid suffix or suffixAlias for the
1697 ber_str2bv( c->argv[ 1 ], 0, 0, &dn );
1698 if ( dnPrettyNormal( NULL, &dn, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
1699 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1700 "suffix \"%s\" is invalid",
1702 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1706 for ( j = 0; !BER_BVISNULL( &c->be->be_nsuffix[ j ] ); j++ ) {
1707 if ( dnIsSuffix( &nvnc, &c->be->be_nsuffix[ 0 ] ) ) {
1712 if ( BER_BVISNULL( &c->be->be_nsuffix[ j ] ) ) {
1713 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1714 "suffix \"%s\" must be within the database naming context",
1716 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1717 free( pvnc.bv_val );
1718 free( nvnc.bv_val );
1722 ber_str2bv( c->argv[ 2 ], 0, 0, &dn );
1723 if ( dnPrettyNormal( NULL, &dn, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
1724 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1725 "massaged suffix \"%s\" is invalid",
1727 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1728 free( pvnc.bv_val );
1729 free( nvnc.bv_val );
1733 tmp_bd = select_backend( &nrnc, 0 );
1734 if ( tmp_bd != NULL && tmp_bd->be_private == c->be->be_private ) {
1735 Debug( LDAP_DEBUG_ANY,
1736 "%s: warning: <massaged suffix> \"%s\" resolves to this database, in "
1737 "\"suffixMassage <suffix> <massaged suffix>\"\n",
1738 c->log, prnc.bv_val, 0 );
1742 * The suffix massaging is emulated by means of the
1743 * rewrite capabilities
1745 rc = suffix_massage_config( mi->mi_targets[ i ]->mt_rwmap.rwm_rw,
1746 &pvnc, &nvnc, &prnc, &nrnc );
1748 free( pvnc.bv_val );
1749 free( nvnc.bv_val );
1750 free( prnc.bv_val );
1751 free( nrnc.bv_val );
1756 case LDAP_BACK_CFG_REWRITE:
1757 /* rewrite stuff ... */
1758 i = mi->mi_ntargets - 1;
1761 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1762 "need \"uri\" directive first" );
1763 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1767 return rewrite_parse( mi->mi_targets[ i ]->mt_rwmap.rwm_rw,
1768 c->fname, c->lineno, c->argc, c->argv );
1770 case LDAP_BACK_CFG_MAP:
1771 /* objectclass/attribute mapping */
1772 i = mi->mi_ntargets - 1;
1775 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1776 "need \"uri\" directive first" );
1777 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1781 return ldap_back_map_config( c, &mi->mi_targets[ i ]->mt_rwmap.rwm_oc,
1782 &mi->mi_targets[ i ]->mt_rwmap.rwm_at );
1784 case LDAP_BACK_CFG_NRETRIES: {
1785 int nretries = META_RETRY_UNDEFINED;
1787 i = mi->mi_ntargets - 1;
1789 if ( strcasecmp( c->argv[ 1 ], "forever" ) == 0 ) {
1790 nretries = META_RETRY_FOREVER;
1792 } else if ( strcasecmp( c->argv[ 1 ], "never" ) == 0 ) {
1793 nretries = META_RETRY_NEVER;
1796 if ( lutil_atoi( &nretries, c->argv[ 1 ] ) != 0 ) {
1797 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1798 "unable to parse nretries {never|forever|<retries>}: \"%s\"",
1800 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1806 mi->mi_nretries = nretries;
1809 mi->mi_targets[ i ]->mt_nretries = nretries;
1813 case LDAP_BACK_CFG_VERSION: {
1814 int *version = mi->mi_ntargets ?
1815 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_version
1818 if ( *version != 0 && ( *version < LDAP_VERSION_MIN || *version > LDAP_VERSION_MAX ) ) {
1819 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1820 "unsupported protocol version \"%s\"",
1822 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1827 case LDAP_BACK_CFG_NOREFS: {
1828 /* do not return search references */
1829 unsigned *flagsp = mi->mi_ntargets ?
1830 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
1833 if ( c->value_int ) {
1834 *flagsp |= LDAP_BACK_F_NOREFS;
1836 *flagsp &= ~LDAP_BACK_F_NOREFS;
1840 case LDAP_BACK_CFG_NOUNDEFFILTER: {
1841 /* do not propagate undefined search filters */
1842 unsigned *flagsp = mi->mi_ntargets ?
1843 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_flags
1846 if ( c->value_int ) {
1847 *flagsp |= LDAP_BACK_F_NOUNDEFFILTER;
1849 *flagsp &= ~LDAP_BACK_F_NOUNDEFFILTER;
1853 #ifdef SLAPD_META_CLIENT_PR
1854 case LDAP_BACK_CFG_CLIENT_PR: {
1855 int *ps = mi->mi_ntargets ?
1856 &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_ps
1859 if ( strcasecmp( c->argv[ 1 ], "accept-unsolicited" ) == 0 ) {
1860 *ps = META_CLIENT_PR_ACCEPT_UNSOLICITED;
1862 } else if ( strcasecmp( c->argv[ 1 ], "disable" ) == 0 ) {
1863 *ps = META_CLIENT_PR_DISABLE;
1865 } else if ( lutil_atoi( ps, c->argv[ 1 ] ) || *ps < -1 ) {
1866 snprintf( c->cr_msg, sizeof( c->cr_msg ),
1867 "unable to parse client-pr {accept-unsolicited|disable|<size>}: \"%s\"",
1869 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1873 #endif /* SLAPD_META_CLIENT_PR */
1877 return SLAP_CONF_UNKNOWN;
1884 meta_back_init_cf( BackendInfo *bi )
1887 AttributeDescription *ad = NULL;
1890 /* Make sure we don't exceed the bits reserved for userland */
1891 config_check_userland( LDAP_BACK_CFG_LAST );
1893 bi->bi_cf_ocs = metaocs;
1895 rc = config_register_schema( metacfg, metaocs );
1900 /* setup olcDbAclPasswd and olcDbIDAssertPasswd
1901 * to be base64-encoded when written in LDIF form;
1902 * basically, we don't care if it fails */
1903 rc = slap_str2ad( "olcDbACLPasswd", &ad, &text );
1905 Debug( LDAP_DEBUG_ANY, "config_back_initialize: "
1906 "warning, unable to get \"olcDbACLPasswd\" "
1907 "attribute description: %d: %s\n",
1910 (void)ldif_must_b64_encode_register( ad->ad_cname.bv_val,
1911 ad->ad_type->sat_oid );
1915 rc = slap_str2ad( "olcDbIDAssertPasswd", &ad, &text );
1917 Debug( LDAP_DEBUG_ANY, "config_back_initialize: "
1918 "warning, unable to get \"olcDbIDAssertPasswd\" "
1919 "attribute description: %d: %s\n",
1922 (void)ldif_must_b64_encode_register( ad->ad_cname.bv_val,
1923 ad->ad_type->sat_oid );
1930 ldap_back_map_config(
1932 struct ldapmap *oc_map,
1933 struct ldapmap *at_map )
1935 struct ldapmap *map;
1936 struct ldapmapping *mapping;
1940 if ( strcasecmp( c->argv[ 1 ], "objectclass" ) == 0 ) {
1944 } else if ( strcasecmp( c->argv[ 1 ], "attribute" ) == 0 ) {
1948 snprintf( c->cr_msg, sizeof(c->cr_msg),
1949 "%s unknown argument \"%s\"",
1950 c->argv[0], c->argv[1] );
1951 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1955 if ( !is_oc && map->map == NULL ) {
1956 /* only init if required */
1957 ldap_back_map_init( map, &mapping );
1960 if ( strcmp( c->argv[ 2 ], "*" ) == 0 ) {
1961 if ( c->argc < 4 || strcmp( c->argv[ 3 ], "*" ) == 0 ) {
1962 map->drop_missing = ( c->argc < 4 );
1963 goto success_return;
1965 src = dst = c->argv[ 3 ];
1967 } else if ( c->argc < 4 ) {
1973 dst = ( strcmp( c->argv[ 3 ], "*" ) == 0 ? src : c->argv[ 3 ] );
1976 if ( ( map == at_map )
1977 && ( strcasecmp( src, "objectclass" ) == 0
1978 || strcasecmp( dst, "objectclass" ) == 0 ) )
1980 snprintf( c->cr_msg, sizeof(c->cr_msg),
1981 "objectclass attribute cannot be mapped" );
1982 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1986 mapping = (struct ldapmapping *)ch_calloc( 2,
1987 sizeof(struct ldapmapping) );
1988 if ( mapping == NULL ) {
1989 snprintf( c->cr_msg, sizeof(c->cr_msg),
1991 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
1994 ber_str2bv( src, 0, 1, &mapping[ 0 ].src );
1995 ber_str2bv( dst, 0, 1, &mapping[ 0 ].dst );
1996 mapping[ 1 ].src = mapping[ 0 ].dst;
1997 mapping[ 1 ].dst = mapping[ 0 ].src;
2003 if ( src[ 0 ] != '\0' ) {
2004 if ( oc_bvfind( &mapping[ 0 ].src ) == NULL ) {
2005 Debug( LDAP_DEBUG_ANY,
2006 "warning, source objectClass '%s' should be defined in schema\n",
2010 * FIXME: this should become an err
2016 if ( oc_bvfind( &mapping[ 0 ].dst ) == NULL ) {
2017 Debug( LDAP_DEBUG_ANY,
2018 "warning, destination objectClass '%s' is not defined in schema\n",
2023 const char *text = NULL;
2024 AttributeDescription *ad = NULL;
2026 if ( src[ 0 ] != '\0' ) {
2027 rc = slap_bv2ad( &mapping[ 0 ].src, &ad, &text );
2028 if ( rc != LDAP_SUCCESS ) {
2029 Debug( LDAP_DEBUG_ANY,
2030 "warning, source attributeType '%s' should be defined in schema\n",
2034 * FIXME: this should become an err
2037 * we create a fake "proxied" ad
2041 rc = slap_bv2undef_ad( &mapping[ 0 ].src,
2042 &ad, &text, SLAP_AD_PROXIED );
2043 if ( rc != LDAP_SUCCESS ) {
2044 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2045 "source attributeType \"%s\": %d (%s)",
2046 src, rc, text ? text : "" );
2047 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2055 rc = slap_bv2ad( &mapping[ 0 ].dst, &ad, &text );
2056 if ( rc != LDAP_SUCCESS ) {
2057 Debug( LDAP_DEBUG_ANY,
2058 "warning, destination attributeType '%s' is not defined in schema\n",
2062 * we create a fake "proxied" ad
2066 rc = slap_bv2undef_ad( &mapping[ 0 ].dst,
2067 &ad, &text, SLAP_AD_PROXIED );
2068 if ( rc != LDAP_SUCCESS ) {
2069 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2070 "destination attributeType \"%s\": %d (%s)\n",
2071 dst, rc, text ? text : "" );
2072 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2078 if ( (src[ 0 ] != '\0' && avl_find( map->map, (caddr_t)&mapping[ 0 ], mapping_cmp ) != NULL)
2079 || avl_find( map->remap, (caddr_t)&mapping[ 1 ], mapping_cmp ) != NULL)
2081 snprintf( c->cr_msg, sizeof( c->cr_msg ),
2082 "duplicate mapping found." );
2083 Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg, 0 );
2087 if ( src[ 0 ] != '\0' ) {
2088 avl_insert( &map->map, (caddr_t)&mapping[ 0 ],
2089 mapping_cmp, mapping_dup );
2091 avl_insert( &map->remap, (caddr_t)&mapping[ 1 ],
2092 mapping_cmp, mapping_dup );
2099 ch_free( mapping[ 0 ].src.bv_val );
2100 ch_free( mapping[ 0 ].dst.bv_val );
2108 #ifdef ENABLE_REWRITE
2110 suffix_massage_regexize( const char *s )
2116 if ( s[ 0 ] == '\0' ) {
2117 return ch_strdup( "^(.+)$" );
2121 ( r = strchr( p, ',' ) ) != NULL;
2125 res = ch_calloc( sizeof( char ),
2127 + STRLENOF( "((.+),)?" )
2128 + STRLENOF( "[ ]?" ) * i
2129 + STRLENOF( "$" ) + 1 );
2131 ptr = lutil_strcopy( res, "((.+),)?" );
2133 ( r = strchr( p, ',' ) ) != NULL;
2135 ptr = lutil_strncopy( ptr, p, r - p + 1 );
2136 ptr = lutil_strcopy( ptr, "[ ]?" );
2138 if ( r[ 1 ] == ' ' ) {
2142 ptr = lutil_strcopy( ptr, p );
2151 suffix_massage_patternize( const char *s, const char *p )
2158 if ( s[ 0 ] == '\0' ) {
2162 res = ch_calloc( sizeof( char ), len + STRLENOF( "%1" ) + 1 );
2163 if ( res == NULL ) {
2167 ptr = lutil_strcopy( res, ( p[ 0 ] == '\0' ? "%2" : "%1" ) );
2168 if ( s[ 0 ] == '\0' ) {
2172 lutil_strcopy( ptr, p );
2178 suffix_massage_config(
2179 struct rewrite_info *info,
2180 struct berval *pvnc,
2181 struct berval *nvnc,
2182 struct berval *prnc,
2189 rargv[ 0 ] = "rewriteEngine";
2192 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
2194 rargv[ 0 ] = "rewriteContext";
2195 rargv[ 1 ] = "default";
2197 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
2199 rargv[ 0 ] = "rewriteRule";
2200 rargv[ 1 ] = suffix_massage_regexize( pvnc->bv_val );
2201 rargv[ 2 ] = suffix_massage_patternize( pvnc->bv_val, prnc->bv_val );
2204 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
2205 ch_free( rargv[ 1 ] );
2206 ch_free( rargv[ 2 ] );
2208 if ( BER_BVISEMPTY( pvnc ) ) {
2209 rargv[ 0 ] = "rewriteRule";
2211 rargv[ 2 ] = prnc->bv_val;
2214 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
2217 rargv[ 0 ] = "rewriteContext";
2218 rargv[ 1 ] = "searchEntryDN";
2220 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
2222 rargv[ 0 ] = "rewriteRule";
2223 rargv[ 1 ] = suffix_massage_regexize( prnc->bv_val );
2224 rargv[ 2 ] = suffix_massage_patternize( prnc->bv_val, pvnc->bv_val );
2227 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
2228 ch_free( rargv[ 1 ] );
2229 ch_free( rargv[ 2 ] );
2231 if ( BER_BVISEMPTY( prnc ) ) {
2232 rargv[ 0 ] = "rewriteRule";
2234 rargv[ 2 ] = pvnc->bv_val;
2237 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
2240 /* backward compatibility */
2241 rargv[ 0 ] = "rewriteContext";
2242 rargv[ 1 ] = "searchResult";
2243 rargv[ 2 ] = "alias";
2244 rargv[ 3 ] = "searchEntryDN";
2246 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
2248 rargv[ 0 ] = "rewriteContext";
2249 rargv[ 1 ] = "matchedDN";
2250 rargv[ 2 ] = "alias";
2251 rargv[ 3 ] = "searchEntryDN";
2253 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
2255 rargv[ 0 ] = "rewriteContext";
2256 rargv[ 1 ] = "searchAttrDN";
2257 rargv[ 2 ] = "alias";
2258 rargv[ 3 ] = "searchEntryDN";
2260 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
2262 /* NOTE: this corresponds to #undef'ining RWM_REFERRAL_REWRITE;
2263 * see servers/slapd/overlays/rwm.h for details */
2264 rargv[ 0 ] = "rewriteContext";
2265 rargv[ 1 ] = "referralAttrDN";
2267 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
2269 rargv[ 0 ] = "rewriteContext";
2270 rargv[ 1 ] = "referralDN";
2272 rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
2276 #endif /* ENABLE_REWRITE */