/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1999-2022 The OpenLDAP Foundation. * Portions Copyright 2001-2003 Pierangelo Masarati. * Portions Copyright 1999-2003 Howard Chu. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * . */ /* ACKNOWLEDGEMENTS: * This work was initially developed by the Howard Chu for inclusion * in OpenLDAP Software and subsequently enhanced by Pierangelo * Masarati. */ #include "portable.h" #include #include #include #include #include "slap.h" #include "slap-config.h" #include "lutil.h" #include "ldif.h" #include "../back-ldap/back-ldap.h" #include "back-meta.h" #ifdef LDAP_DEVEL #define SLAP_AUTH_DN 1 #endif static ConfigDriver meta_back_cf_gen; static ConfigLDAPadd meta_ldadd; static ConfigCfAdd meta_cfadd; static int ldap_back_map_config( ConfigArgs *c, struct ldapmap *oc_map, struct ldapmap *at_map ); /* Three sets of enums: * 1) attrs that are only valid in the base config * 2) attrs that are valid in base or target * 3) attrs that are only valid in a target */ /* Base attrs */ enum { LDAP_BACK_CFG_CONN_TTL = 1, LDAP_BACK_CFG_DNCACHE_TTL, LDAP_BACK_CFG_IDLE_TIMEOUT, LDAP_BACK_CFG_ONERR, LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER, LDAP_BACK_CFG_SINGLECONN, LDAP_BACK_CFG_USETEMP, LDAP_BACK_CFG_CONNPOOLMAX, LDAP_BACK_CFG_LAST_BASE }; /* Base or target */ enum { LDAP_BACK_CFG_BIND_TIMEOUT = LDAP_BACK_CFG_LAST_BASE, LDAP_BACK_CFG_CANCEL, LDAP_BACK_CFG_CHASE, LDAP_BACK_CFG_CLIENT_PR, LDAP_BACK_CFG_DEFAULT_T, LDAP_BACK_CFG_NETWORK_TIMEOUT, LDAP_BACK_CFG_NOREFS, LDAP_BACK_CFG_NOUNDEFFILTER, LDAP_BACK_CFG_NRETRIES, LDAP_BACK_CFG_QUARANTINE, LDAP_BACK_CFG_REBIND, LDAP_BACK_CFG_TIMEOUT, LDAP_BACK_CFG_VERSION, LDAP_BACK_CFG_ST_REQUEST, LDAP_BACK_CFG_T_F, LDAP_BACK_CFG_TLS, LDAP_BACK_CFG_LAST_BOTH }; /* Target attrs */ enum { LDAP_BACK_CFG_URI = LDAP_BACK_CFG_LAST_BOTH, LDAP_BACK_CFG_IDASSERT_AUTHZFROM, LDAP_BACK_CFG_IDASSERT_BIND, LDAP_BACK_CFG_REWRITE, LDAP_BACK_CFG_SUFFIXM, LDAP_BACK_CFG_MAP, LDAP_BACK_CFG_SUBTREE_EX, LDAP_BACK_CFG_SUBTREE_IN, LDAP_BACK_CFG_PSEUDOROOTDN, LDAP_BACK_CFG_PSEUDOROOTPW, LDAP_BACK_CFG_KEEPALIVE, LDAP_BACK_CFG_TCP_USER_TIMEOUT, LDAP_BACK_CFG_FILTER, LDAP_BACK_CFG_LAST }; static ConfigTable metacfg[] = { { "uri", "uri", 2, 0, 0, ARG_MAGIC|LDAP_BACK_CFG_URI, meta_back_cf_gen, "( OLcfgDbAt:0.14 " "NAME 'olcDbURI' " "DESC 'URI (list) for remote DSA' " "EQUALITY caseExactMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "tls", "what", 2, 0, 0, ARG_MAGIC|LDAP_BACK_CFG_TLS, meta_back_cf_gen, "( OLcfgDbAt:3.1 " "NAME 'olcDbStartTLS' " "DESC 'StartTLS' " "EQUALITY caseExactMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "idassert-bind", "args", 2, 0, 0, ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_BIND, meta_back_cf_gen, "( OLcfgDbAt:3.7 " "NAME 'olcDbIDAssertBind' " "DESC 'Remote Identity Assertion administrative identity auth bind configuration' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "idassert-authzFrom", "authzRule", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_IDASSERT_AUTHZFROM, meta_back_cf_gen, "( OLcfgDbAt:3.9 " "NAME 'olcDbIDAssertAuthzFrom' " "DESC 'Remote Identity Assertion authz rules' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "X-ORDERED 'VALUES' )", NULL, NULL }, { "rebind-as-user", "true|FALSE", 1, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_REBIND, meta_back_cf_gen, "( OLcfgDbAt:3.10 " "NAME 'olcDbRebindAsUser' " "DESC 'Rebind as user' " "EQUALITY booleanMatch " "SYNTAX OMsBoolean " "SINGLE-VALUE )", NULL, NULL }, { "chase-referrals", "true|FALSE", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_CHASE, meta_back_cf_gen, "( OLcfgDbAt:3.11 " "NAME 'olcDbChaseReferrals' " "DESC 'Chase referrals' " "EQUALITY booleanMatch " "SYNTAX OMsBoolean " "SINGLE-VALUE )", NULL, NULL }, { "t-f-support", "true|FALSE|discover", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_T_F, meta_back_cf_gen, "( OLcfgDbAt:3.12 " "NAME 'olcDbTFSupport' " "DESC 'Absolute filters support' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "timeout", "timeout(list)", 2, 0, 0, ARG_MAGIC|LDAP_BACK_CFG_TIMEOUT, meta_back_cf_gen, "( OLcfgDbAt:3.14 " "NAME 'olcDbTimeout' " "DESC 'Per-operation timeouts' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "idle-timeout", "timeout", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_IDLE_TIMEOUT, meta_back_cf_gen, "( OLcfgDbAt:3.15 " "NAME 'olcDbIdleTimeout' " "DESC 'connection idle timeout' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "conn-ttl", "ttl", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_CONN_TTL, meta_back_cf_gen, "( OLcfgDbAt:3.16 " "NAME 'olcDbConnTtl' " "DESC 'connection ttl' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "network-timeout", "timeout", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_NETWORK_TIMEOUT, meta_back_cf_gen, "( OLcfgDbAt:3.17 " "NAME 'olcDbNetworkTimeout' " "DESC 'connection network timeout' " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "protocol-version", "version", 2, 2, 0, ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_VERSION, meta_back_cf_gen, "( OLcfgDbAt:3.18 " "NAME 'olcDbProtocolVersion' " "DESC 'protocol version' " "EQUALITY integerMatch " "SYNTAX OMsInteger " "SINGLE-VALUE )", NULL, NULL }, { "single-conn", "true|FALSE", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_SINGLECONN, meta_back_cf_gen, "( OLcfgDbAt:3.19 " "NAME 'olcDbSingleConn' " "DESC 'cache a single connection per identity' " "EQUALITY booleanMatch " "SYNTAX OMsBoolean " "SINGLE-VALUE )", NULL, NULL }, { "cancel", "ABANDON|ignore|exop", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_CANCEL, meta_back_cf_gen, "( OLcfgDbAt:3.20 " "NAME 'olcDbCancel' " "DESC 'abandon/ignore/exop operations when appropriate' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "quarantine", "retrylist", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_QUARANTINE, meta_back_cf_gen, "( OLcfgDbAt:3.21 " "NAME 'olcDbQuarantine' " "DESC 'Quarantine database if connection fails and retry according to rule' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "use-temporary-conn", "true|FALSE", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_USETEMP, meta_back_cf_gen, "( OLcfgDbAt:3.22 " "NAME 'olcDbUseTemporaryConn' " "DESC 'Use temporary connections if the cached one is busy' " "EQUALITY booleanMatch " "SYNTAX OMsBoolean " "SINGLE-VALUE )", NULL, NULL }, { "conn-pool-max", "", 2, 2, 0, ARG_MAGIC|ARG_INT|LDAP_BACK_CFG_CONNPOOLMAX, meta_back_cf_gen, "( OLcfgDbAt:3.23 " "NAME 'olcDbConnectionPoolMax' " "DESC 'Max size of privileged connections pool' " "EQUALITY integerMatch " "SYNTAX OMsInteger " "SINGLE-VALUE )", NULL, NULL }, #ifdef SLAP_CONTROL_X_SESSION_TRACKING { "session-tracking-request", "true|FALSE", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_ST_REQUEST, meta_back_cf_gen, "( OLcfgDbAt:3.24 " "NAME 'olcDbSessionTrackingRequest' " "DESC 'Add session tracking control to proxied requests' " "EQUALITY booleanMatch " "SYNTAX OMsBoolean " "SINGLE-VALUE )", NULL, NULL }, #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ { "norefs", "true|FALSE", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOREFS, meta_back_cf_gen, "( OLcfgDbAt:3.25 " "NAME 'olcDbNoRefs' " "DESC 'Do not return search reference responses' " "EQUALITY booleanMatch " "SYNTAX OMsBoolean " "SINGLE-VALUE )", NULL, NULL }, { "noundeffilter", "true|FALSE", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_NOUNDEFFILTER, meta_back_cf_gen, "( OLcfgDbAt:3.26 " "NAME 'olcDbNoUndefFilter' " "DESC 'Do not propagate undefined search filters' " "EQUALITY booleanMatch " "SYNTAX OMsBoolean " "SINGLE-VALUE )", NULL, NULL }, { "rewrite", "arglist", 2, 0, STRLENOF( "rewrite" ), ARG_MAGIC|LDAP_BACK_CFG_REWRITE, meta_back_cf_gen, "( OLcfgDbAt:3.101 " "NAME 'olcDbRewrite' " "DESC 'DN rewriting rules' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "X-ORDERED 'VALUES' )", NULL, NULL }, { "suffixmassage", "virtual> [*|] *|]", 1, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_DEFAULT_T, meta_back_cf_gen, "( OLcfgDbAt:3.105 " "NAME 'olcDbDefaultTarget' " "DESC 'Specify the default target' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "dncache-ttl", "ttl", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_DNCACHE_TTL, meta_back_cf_gen, "( OLcfgDbAt:3.106 " "NAME 'olcDbDnCacheTtl' " "DESC 'dncache ttl' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "bind-timeout", "microseconds", 2, 2, 0, ARG_MAGIC|ARG_ULONG|LDAP_BACK_CFG_BIND_TIMEOUT, meta_back_cf_gen, "( OLcfgDbAt:3.107 " "NAME 'olcDbBindTimeout' " "DESC 'bind timeout' " "EQUALITY integerMatch " "SYNTAX OMsInteger " "SINGLE-VALUE )", NULL, NULL }, { "onerr", "CONTINUE|report|stop", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_ONERR, meta_back_cf_gen, "( OLcfgDbAt:3.108 " "NAME 'olcDbOnErr' " "DESC 'error handling' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "pseudoroot-bind-defer", "TRUE|false", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER, meta_back_cf_gen, "( OLcfgDbAt:3.109 " "NAME 'olcDbPseudoRootBindDefer' " "DESC 'error handling' " "EQUALITY booleanMatch " "SYNTAX OMsBoolean " "SINGLE-VALUE )", NULL, NULL }, { "root-bind-defer", "TRUE|false", 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|LDAP_BACK_CFG_PSEUDOROOT_BIND_DEFER, meta_back_cf_gen, NULL, NULL, NULL }, { "pseudorootdn", "dn", 2, 2, 0, ARG_MAGIC|ARG_DN|ARG_QUOTE|LDAP_BACK_CFG_PSEUDOROOTDN, meta_back_cf_gen, NULL, NULL, NULL }, { "pseudorootpw", "password", 2, 2, 0, ARG_MAGIC|ARG_STRING|LDAP_BACK_CFG_PSEUDOROOTPW, meta_back_cf_gen, NULL, NULL, NULL }, { "nretries", "NEVER|forever|", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_NRETRIES, meta_back_cf_gen, "( OLcfgDbAt:3.110 " "NAME 'olcDbNretries' " "DESC 'retry handling' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "client-pr", "accept-unsolicited|disable|", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_CLIENT_PR, meta_back_cf_gen, "( OLcfgDbAt:3.111 " "NAME 'olcDbClientPr' " "DESC 'PagedResults handling' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "", "", 0, 0, 0, ARG_IGNORED, NULL, "( OLcfgDbAt:3.100 NAME 'olcMetaSub' " "DESC 'Placeholder to name a Target entry' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE X-ORDERED 'SIBLINGS' )", NULL, NULL }, { "keepalive", "keepalive", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_KEEPALIVE, meta_back_cf_gen, "( OLcfgDbAt:3.29 " "NAME 'olcDbKeepalive' " "DESC 'TCP keepalive' " "EQUALITY caseIgnoreMatch " "SYNTAX OMsDirectoryString " "SINGLE-VALUE )", NULL, NULL }, { "tcp-user-timeout", "milliseconds", 2, 2, 0, ARG_MAGIC|ARG_UINT|LDAP_BACK_CFG_TCP_USER_TIMEOUT, meta_back_cf_gen, "( OLcfgDbAt:3.30 " "NAME 'olcDbTcpUserTimeout' " "DESC 'TCP User Timeout' " "SYNTAX OMsInteger " "SINGLE-VALUE )", NULL, NULL }, { "filter", "pattern", 2, 2, 0, ARG_MAGIC|LDAP_BACK_CFG_FILTER, meta_back_cf_gen, "( OLcfgDbAt:3.112 " "NAME 'olcDbFilter' " "DESC 'Filter regex pattern to include in target' " "EQUALITY caseExactMatch " "SYNTAX OMsDirectoryString )", NULL, NULL }, { NULL, NULL, 0, 0, 0, ARG_IGNORED, NULL, NULL, NULL, NULL } }; #ifdef SLAP_CONTROL_X_SESSION_TRACKING #define ST_ATTR "$ olcDbSessionTrackingRequest " #else #define ST_ATTR "" #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ #define COMMON_ATTRS \ "$ olcDbBindTimeout " \ "$ olcDbCancel " \ "$ olcDbChaseReferrals " \ "$ olcDbClientPr " \ "$ olcDbDefaultTarget " \ "$ olcDbNetworkTimeout " \ "$ olcDbNoRefs " \ "$ olcDbNoUndefFilter " \ "$ olcDbNretries " \ "$ olcDbProtocolVersion " \ "$ olcDbQuarantine " \ "$ olcDbRebindAsUser " \ ST_ATTR \ "$ olcDbStartTLS " \ "$ olcDbTFSupport " static ConfigOCs metaocs[] = { { "( OLcfgDbOc:3.2 " "NAME 'olcMetaConfig' " "DESC 'Meta backend configuration' " "SUP olcDatabaseConfig " "MAY ( olcDbConnTtl " "$ olcDbDnCacheTtl " "$ olcDbIdleTimeout " "$ olcDbOnErr " "$ olcDbPseudoRootBindDefer " "$ olcDbSingleConn " "$ olcDbUseTemporaryConn " "$ olcDbConnectionPoolMax " /* defaults, may be overridden per-target */ COMMON_ATTRS ") )", Cft_Database, metacfg, NULL, meta_cfadd }, { "( OLcfgDbOc:3.3 " "NAME 'olcMetaTargetConfig' " "DESC 'Meta target configuration' " "SUP olcConfig STRUCTURAL " "MUST ( olcMetaSub $ olcDbURI ) " "MAY ( olcDbIDAssertAuthzFrom " "$ olcDbIDAssertBind " "$ olcDbMap " "$ olcDbRewrite " "$ olcDbSubtreeExclude " "$ olcDbSubtreeInclude " "$ olcDbTimeout " "$ olcDbKeepalive " "$ olcDbTcpUserTimeout " "$ olcDbFilter " /* defaults may be inherited */ COMMON_ATTRS ") )", Cft_Misc, metacfg, meta_ldadd }, { NULL, 0, NULL } }; static int meta_ldadd( CfEntryInfo *p, Entry *e, ConfigArgs *c ) { if ( p->ce_type != Cft_Database || !p->ce_be || p->ce_be->be_cf_ocs != metaocs ) return LDAP_CONSTRAINT_VIOLATION; c->be = p->ce_be; return LDAP_SUCCESS; } static int meta_cfadd( Operation *op, SlapReply *rs, Entry *p, ConfigArgs *c ) { metainfo_t *mi = ( metainfo_t * )c->be->be_private; struct berval bv; int i; bv.bv_val = c->cr_msg; for ( i=0; imi_ntargets; i++ ) { bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "olcMetaSub=" SLAP_X_ORDERED_FMT "uri", i ); c->ca_private = mi->mi_targets[i]; c->valx = i; config_build_entry( op, rs, p->e_private, c, &bv, &metaocs[1], NULL ); } return LDAP_SUCCESS; } static int meta_rwi_init( struct rewrite_info **rwm_rw ) { char *rargv[ 3 ]; *rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT ); if ( *rwm_rw == NULL ) { return -1; } /* * the filter rewrite as a string must be disabled * by default; it can be re-enabled by adding rules; * this creates an empty rewriteContext */ rargv[ 0 ] = "rewriteContext"; rargv[ 1 ] = "searchFilter"; rargv[ 2 ] = NULL; rewrite_parse( *rwm_rw, "", 1, 2, rargv ); rargv[ 0 ] = "rewriteContext"; rargv[ 1 ] = "default"; rargv[ 2 ] = NULL; rewrite_parse( *rwm_rw, "", 1, 2, rargv ); return 0; } static int meta_back_new_target( metatarget_t **mtp ) { metatarget_t *mt; *mtp = NULL; mt = ch_calloc( sizeof( metatarget_t ), 1 ); if ( meta_rwi_init( &mt->mt_rwmap.rwm_rw )) { ch_free( mt ); return -1; } ldap_pvt_thread_mutex_init( &mt->mt_uri_mutex ); mt->mt_idassert_mode = LDAP_BACK_IDASSERT_LEGACY; mt->mt_idassert_authmethod = LDAP_AUTH_NONE; mt->mt_idassert_tls = SB_TLS_DEFAULT; /* by default, use proxyAuthz control on each operation */ mt->mt_idassert_flags = LDAP_BACK_AUTH_PRESCRIPTIVE; *mtp = mt; return 0; } /* Validation for suffixmassage_config */ static int meta_suffixm_config( ConfigArgs *c, int argc, char **argv, metatarget_t *mt ) { BackendDB *tmp_bd; struct berval dn, nvnc, pvnc, nrnc, prnc; int j, rc; /* * syntax: * * suffixmassage * * the field must be defined as a valid suffix * (or suffixAlias?) for the current database; * the shouldn't have already been * defined as a valid suffix or suffixAlias for the * current server */ ber_str2bv( argv[ 1 ], 0, 0, &dn ); if ( dnPrettyNormal( NULL, &dn, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "suffix \"%s\" is invalid", argv[1] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); return 1; } for ( j = 0; !BER_BVISNULL( &c->be->be_nsuffix[ j ] ); j++ ) { if ( dnIsSuffix( &nvnc, &c->be->be_nsuffix[ 0 ] ) ) { break; } } if ( BER_BVISNULL( &c->be->be_nsuffix[ j ] ) ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "suffix \"%s\" must be within the database naming context", argv[1] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); free( pvnc.bv_val ); free( nvnc.bv_val ); return 1; } ber_str2bv( argv[ 2 ], 0, 0, &dn ); if ( dnPrettyNormal( NULL, &dn, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) { snprintf( c->cr_msg, sizeof( c->cr_msg ), "massaged suffix \"%s\" is invalid", argv[2] ); Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->cr_msg ); free( pvnc.bv_val ); free( nvnc.bv_val ); return 1; } tmp_bd = select_backend( &nrnc, 0 ); if ( tmp_bd != NULL && tmp_bd->be_private == c->be->be_private ) { Debug( LDAP_DEBUG_ANY, "%s: warning: \"%s\" resolves to this database, in " "\"suffixMassage \"\n", c->log, prnc.bv_val ); } /* * The suffix massaging is emulated by means of the * rewrite capabilities */ rc = suffix_massage_config( mt->mt_rwmap.rwm_rw, &pvnc, &nvnc, &prnc, &nrnc ); free( pvnc.bv_val ); free( nvnc.bv_val ); free( prnc.bv_val ); free( nrnc.bv_val ); return rc; } int meta_subtree_free( metasubtree_t *ms ) { switch ( ms->ms_type ) { case META_ST_SUBTREE: case META_ST_SUBORDINATE: ber_memfree( ms->ms_dn.bv_val ); break; case META_ST_REGEX: regfree( &ms->ms_regex ); ber_memfree( ms->ms_regex_pattern.bv_val ); break; default: return -1; } ch_free( ms ); return 0; } int meta_subtree_destroy( metasubtree_t *ms ) { if ( ms->ms_next ) { meta_subtree_destroy( ms->ms_next ); } return meta_subtree_free( ms ); } static void meta_filter_free( metafilter_t *mf ) { regfree( &mf->mf_regex ); ber_memfree( mf->mf_regex_pattern.bv_val ); ch_free( mf ); } void meta_filter_destroy( metafilter_t *mf ) { if ( mf->mf_next ) meta_filter_destroy( mf->mf_next ); meta_filter_free( mf ); } static struct berval st_styles[] = { BER_BVC("subtree"), BER_BVC("children"), BER_BVC("regex") }; static int meta_subtree_unparse( ConfigArgs *c, metatarget_t *mt ) { metasubtree_t *ms; struct berval bv, *style; if ( !mt->mt_subtree ) return 1; /* can only be one of exclude or include */ if (( c->type == LDAP_BACK_CFG_SUBTREE_EX ) ^ mt->mt_subtree_exclude ) return 1; bv.bv_val = c->cr_msg; for ( ms=mt->mt_subtree; ms; ms=ms->ms_next ) { if (ms->ms_type == META_ST_SUBTREE) style = &st_styles[0]; else if ( ms->ms_type == META_ST_SUBORDINATE ) style = &st_styles[1]; else if ( ms->ms_type == META_ST_REGEX ) style = &st_styles[2]; else { assert(0); continue; } bv.bv_len = snprintf( c->cr_msg, sizeof(c->cr_msg), "dn.%s:%s", style->bv_val, ms->ms_dn.bv_val ); value_add_one( &c->rvalue_vals, &bv ); } return 0; } static int meta_subtree_config( metatarget_t *mt, ConfigArgs *c ) { meta_st_t type = META_ST_SUBTREE; char *pattern; struct berval ndn = BER_BVNULL; metasubtree_t *ms = NULL; if ( c->type == LDAP_BACK_CFG_SUBTREE_EX ) { if ( mt->mt_subtree && !mt->mt_subtree_exclude ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"subtree-exclude\" incompatible with previous \"subtree-include\" directives" ); return 1; } mt->mt_subtree_exclude = 1; } else { if ( mt->mt_subtree && mt->mt_subtree_exclude ) { snprintf( c->cr_msg, sizeof(c->cr_msg), "\"subtree-include\" incompatible with previous \"subtree-exclude\" directives" ); return 1; } } pattern = c->argv[1]; if ( strncasecmp( pattern, "dn", STRLENOF( "dn" ) ) == 0 ) { char *style; pattern = &pattern[STRLENOF( "dn")]; if ( pattern[0] == '.' ) { style = &pattern[1]; if ( strncasecmp( style, "subtree", STRLENOF( "subtree" ) ) == 0 ) { type = META_ST_SUBTREE; pattern = &style[STRLENOF( "subtree" )]; } else if ( strncasecmp( style, "children", STRLENOF( "children" ) ) == 0 ) { type = META_ST_SUBORDINATE; pattern = &style[STRLENOF( "children" )]; } else if ( strncasecmp( style, "sub", STRLENOF( "sub" ) ) == 0 ) { type = META_ST_SUBTREE; pattern = &style[STRLENOF( "sub" )]; } else if ( strncasecmp( style, "regex", STRLENOF( "regex" ) ) == 0 ) { type = META_ST_REGEX; pattern = &style[STRLENOF( "regex" )]; } else { snprintf( c->cr_msg, sizeof(c->cr_msg), "unknown style in \"dn.