mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-02-15 00:33:43 -05:00
add support for subtree-include (ITS#6801); improve support for subtree-exclude
This commit is contained in:
parent
35c2869e44
commit
34a21b7f40
5 changed files with 472 additions and 89 deletions
|
|
@ -570,13 +570,58 @@ specification.
|
|||
The rewrite options are described in the "REWRITING" section.
|
||||
|
||||
.TP
|
||||
.B subtree\-exclude "<DN>"
|
||||
This directive instructs back-meta to ignore the current target
|
||||
for operations whose requestDN is subordinate to
|
||||
.BR DN .
|
||||
.B subtree\-{exclude|include} "<rule>"
|
||||
This directive allows to indicate what subtrees are actually served
|
||||
by a target.
|
||||
The syntax of the supported rules is
|
||||
|
||||
\fB<rule>: [dn[.<style>]:]<pattern>\fP
|
||||
|
||||
\fB<style>: subtree|children|regex\fP
|
||||
|
||||
When \fB<style>\fP is either \fBsubtree\fP or \fBchildren\fP
|
||||
the \fB<pattern>\fP is a DN that must be within the naming context
|
||||
served by the target.
|
||||
When \fB<style>\fP is \fBregex\fP the \fB<pattern>\fP is a
|
||||
.BR regex (5)
|
||||
pattern.
|
||||
If the \fBdn.<style>:\fP prefix is omitted, \fBdn.subtree:\fP
|
||||
is implicitly assumed for backward compatibility.
|
||||
|
||||
In the
|
||||
.B subtree\-exclude
|
||||
form if the \fIrequest DN\fP matches at least one rule,
|
||||
the target is not considered while fulfilling the request;
|
||||
otherwise, the target is considered based on the value of the \fIrequest DN\fP.
|
||||
When the request is a search, also the \fIscope\fP is considered.
|
||||
|
||||
In the
|
||||
.B subtree\-include
|
||||
form if the \fIrequest DN\fP matches at least one rule,
|
||||
the target is considered while fulfilling the request;
|
||||
otherwise the target is ignored.
|
||||
|
||||
.LP
|
||||
.RS
|
||||
.nf
|
||||
| match | exclude |
|
||||
+---------+---------+-------------------+
|
||||
| T | T | not candidate |
|
||||
| F | T | continue checking |
|
||||
+---------+---------+-------------------+
|
||||
| T | F | candidate |
|
||||
| F | F | not candidate |
|
||||
+---------+---------+-------------------+
|
||||
.fi
|
||||
|
||||
.RE
|
||||
.RS
|
||||
There may be multiple occurrences of the
|
||||
.B subtree\-exclude
|
||||
directive for each of the targets.
|
||||
or
|
||||
.B subtree\-include
|
||||
directive for each of the targets, but they are mutually exclusive.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
.B suffixmassage "<virtual naming context>" "<real naming context>"
|
||||
|
|
|
|||
|
|
@ -259,6 +259,31 @@ typedef struct metaconn_t {
|
|||
* in one block with the metaconn_t structure */
|
||||
} metaconn_t;
|
||||
|
||||
typedef enum meta_st_t {
|
||||
#if 0 /* todo */
|
||||
META_ST_EXACT = LDAP_SCOPE_BASE,
|
||||
#endif
|
||||
META_ST_SUBTREE = LDAP_SCOPE_SUBTREE,
|
||||
META_ST_SUBORDINATE = LDAP_SCOPE_SUBORDINATE,
|
||||
META_ST_REGEX /* last + 1 */
|
||||
} meta_st_t;
|
||||
|
||||
typedef struct metasubtree_t {
|
||||
meta_st_t ms_type;
|
||||
union {
|
||||
struct berval msu_dn;
|
||||
struct {
|
||||
regex_t msr_regex;
|
||||
char *msr_regex_pattern;
|
||||
} msu_regex;
|
||||
} ms_un;
|
||||
#define ms_dn ms_un.msu_dn
|
||||
#define ms_regex ms_un.msu_regex.msr_regex
|
||||
#define ms_regex_pattern ms_un.msu_regex.msr_regex_pattern
|
||||
|
||||
struct metasubtree_t *ms_next;
|
||||
} metasubtree_t;
|
||||
|
||||
typedef struct metatarget_t {
|
||||
char *mt_uri;
|
||||
ldap_pvt_thread_mutex_t mt_uri_mutex;
|
||||
|
|
@ -269,7 +294,10 @@ typedef struct metatarget_t {
|
|||
LDAP_URLLIST_PROC *mt_urllist_f;
|
||||
void *mt_urllist_p;
|
||||
|
||||
BerVarray mt_subtree_exclude;
|
||||
metasubtree_t *mt_subtree;
|
||||
/* F: subtree-include; T: subtree-exclude */
|
||||
int mt_subtree_exclude;
|
||||
|
||||
int mt_scope;
|
||||
|
||||
struct berval mt_psuffix; /* pretty suffix */
|
||||
|
|
@ -636,6 +664,9 @@ meta_dncache_delete_entry(
|
|||
extern void
|
||||
meta_dncache_free( void *entry );
|
||||
|
||||
extern int
|
||||
meta_subtree_destroy( metasubtree_t *ms );
|
||||
|
||||
extern LDAP_REBIND_PROC meta_back_default_rebind;
|
||||
extern LDAP_URLLIST_PROC meta_back_default_urllist;
|
||||
|
||||
|
|
|
|||
|
|
@ -32,25 +32,58 @@
|
|||
/*
|
||||
* The meta-directory has one suffix, called <suffix>.
|
||||
* It handles a pool of target servers, each with a branch suffix
|
||||
* of the form <branch X>,<suffix>
|
||||
* of the form <branch X>,<suffix>, where <branch X> may be empty.
|
||||
*
|
||||
* When the meta-directory receives a request with a dn that belongs
|
||||
* to a branch, the corresponding target is invoked. When the dn
|
||||
* When the meta-directory receives a request with a request DN that belongs
|
||||
* to a branch, the corresponding target is invoked. When the request DN
|
||||
* does not belong to a specific branch, all the targets that
|
||||
* are compatible with the dn are selected as candidates, and
|
||||
* are compatible with the request DN are selected as candidates, and
|
||||
* the request is spawned to all the candidate targets
|
||||
*
|
||||
* A request is characterized by a dn. The following cases are handled:
|
||||
* - the dn is the suffix: <dn> == <suffix>,
|
||||
* A request is characterized by a request DN. The following cases are
|
||||
* handled:
|
||||
* - the request DN is the suffix: <dn> == <suffix>,
|
||||
* all the targets are candidates (search ...)
|
||||
* - the dn is a branch suffix: <dn> == <branch X>,<suffix>, or
|
||||
* - the dn is a subtree of a branch suffix:
|
||||
* - the request DN is a branch suffix: <dn> == <branch X>,<suffix>, or
|
||||
* - the request DN is a subtree of a branch suffix:
|
||||
* <dn> == <rdn>,<branch X>,<suffix>,
|
||||
* the target is the only candidate.
|
||||
*
|
||||
* A possible extension will include the handling of multiple suffixes
|
||||
*/
|
||||
|
||||
static metasubtree_t *
|
||||
meta_subtree_match( metatarget_t *mt, struct berval *ndn, int scope )
|
||||
{
|
||||
metasubtree_t *ms = mt->mt_subtree;
|
||||
|
||||
for ( ms = mt->mt_subtree; ms; ms = ms->ms_next ) {
|
||||
switch ( ms->ms_type ) {
|
||||
case META_ST_SUBTREE:
|
||||
if ( dnIsSuffix( ndn, &ms->ms_dn ) ) {
|
||||
return ms;
|
||||
}
|
||||
break;
|
||||
|
||||
case META_ST_SUBORDINATE:
|
||||
if ( dnIsSuffix( ndn, &ms->ms_dn ) &&
|
||||
( ndn->bv_len > ms->ms_dn.bv_len || scope != LDAP_SCOPE_BASE ) )
|
||||
{
|
||||
return ms;
|
||||
}
|
||||
break;
|
||||
|
||||
case META_ST_REGEX:
|
||||
/* NOTE: cannot handle scope */
|
||||
if ( regexec( &ms->ms_regex, ndn->bv_val, 0, NULL, 0 ) == 0 ) {
|
||||
return ms;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns 1 if suffix is candidate for dn, otherwise 0
|
||||
|
|
@ -70,14 +103,27 @@ meta_back_is_candidate(
|
|||
if ( !dnIsSuffix( ndn, &mt->mt_nsuffix ) ) {
|
||||
return META_NOT_CANDIDATE;
|
||||
}
|
||||
|
||||
if ( mt->mt_subtree_exclude ) {
|
||||
int i;
|
||||
|
||||
for ( i = 0; !BER_BVISNULL( &mt->mt_subtree_exclude[ i ] ); i++ ) {
|
||||
if ( dnIsSuffix( ndn, &mt->mt_subtree_exclude[ i ] ) ) {
|
||||
return META_NOT_CANDIDATE;
|
||||
}
|
||||
/*
|
||||
* | match | exclude |
|
||||
* +---------+---------+-------------------+
|
||||
* | T | T | not candidate |
|
||||
* | F | T | continue checking |
|
||||
* +---------+---------+-------------------+
|
||||
* | T | F | candidate |
|
||||
* | F | F | not candidate |
|
||||
* +---------+---------+-------------------+
|
||||
*/
|
||||
|
||||
if ( mt->mt_subtree ) {
|
||||
int match = ( meta_subtree_match( mt, ndn, scope ) != NULL );
|
||||
|
||||
if ( !mt->mt_subtree_exclude ) {
|
||||
return match ? META_CANDIDATE : META_NOT_CANDIDATE;
|
||||
}
|
||||
|
||||
if ( match /* && mt->mt_subtree_exclude */ ) {
|
||||
return META_NOT_CANDIDATE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,312 @@ check_true_false( char *str )
|
|||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
meta_subtree_destroy( metasubtree_t *ms )
|
||||
{
|
||||
if ( ms->ms_next ) {
|
||||
meta_subtree_destroy( ms->ms_next );
|
||||
}
|
||||
|
||||
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 );
|
||||
ch_free( ms->ms_regex_pattern );
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
ch_free( ms );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
meta_subtree_config(
|
||||
metatarget_t *mt,
|
||||
int argc,
|
||||
char **argv,
|
||||
char *buf,
|
||||
ber_len_t buflen,
|
||||
char *log_prefix )
|
||||
{
|
||||
meta_st_t type = META_ST_SUBTREE;
|
||||
char *pattern;
|
||||
struct berval ndn = BER_BVNULL;
|
||||
metasubtree_t *ms = NULL;
|
||||
|
||||
if ( strcasecmp( argv[0], "subtree-exclude" ) == 0 ) {
|
||||
if ( mt->mt_subtree && !mt->mt_subtree_exclude ) {
|
||||
snprintf( buf, buflen,
|
||||
"\"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( buf, buflen,
|
||||
"\"subtree-include\" incompatible with previous \"subtree-exclude\" directives" );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch ( argc ) {
|
||||
case 1:
|
||||
snprintf( buf, buflen, "missing pattern" );
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
break;
|
||||
|
||||
default:
|
||||
snprintf( buf, buflen, "too many args" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
pattern = 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( buf, buflen, "unknown style in \"dn.<style>\"" );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( pattern[0] != ':' ) {
|
||||
snprintf( buf, buflen, "missing colon after \"dn.<style>\"" );
|
||||
return 1;
|
||||
}
|
||||
pattern++;
|
||||
}
|
||||
|
||||
switch ( type ) {
|
||||
case META_ST_SUBTREE:
|
||||
case META_ST_SUBORDINATE: {
|
||||
struct berval dn;
|
||||
|
||||
ber_str2bv( pattern, 0, 0, &dn );
|
||||
if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL )
|
||||
!= LDAP_SUCCESS )
|
||||
{
|
||||
snprintf( buf, buflen, "DN=\"%s\" is invalid", pattern );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( !dnIsSuffix( &ndn, &mt->mt_nsuffix ) ) {
|
||||
snprintf( buf, buflen,
|
||||
"DN=\"%s\" is not a subtree of target \"%s\"",
|
||||
pattern, mt->mt_nsuffix.bv_val );
|
||||
ber_memfree( ndn.bv_val );
|
||||
return( 1 );
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
/* silence warnings */
|
||||
break;
|
||||
}
|
||||
|
||||
ms = ch_calloc( sizeof( metasubtree_t ), 1 );
|
||||
ms->ms_type = type;
|
||||
|
||||
switch ( ms->ms_type ) {
|
||||
case META_ST_SUBTREE:
|
||||
case META_ST_SUBORDINATE:
|
||||
ms->ms_dn = ndn;
|
||||
break;
|
||||
|
||||
case META_ST_REGEX: {
|
||||
int rc;
|
||||
|
||||
rc = regcomp( &ms->ms_regex, pattern, REG_EXTENDED|REG_ICASE );
|
||||
if ( rc != 0 ) {
|
||||
char regerr[ SLAP_TEXT_BUFLEN ];
|
||||
|
||||
regerror( rc, &ms->ms_regex, regerr, sizeof(regerr) );
|
||||
|
||||
snprintf( buf, sizeof( buf ),
|
||||
"regular expression \"%s\" bad because of %s",
|
||||
pattern, regerr );
|
||||
ch_free( ms );
|
||||
return 1;
|
||||
}
|
||||
ms->ms_regex_pattern = ch_strdup( pattern );
|
||||
} break;
|
||||
}
|
||||
|
||||
if ( mt->mt_subtree == NULL ) {
|
||||
mt->mt_subtree = ms;
|
||||
|
||||
} else {
|
||||
metasubtree_t **msp;
|
||||
|
||||
for ( msp = &mt->mt_subtree; *msp; ) {
|
||||
switch ( ms->ms_type ) {
|
||||
case META_ST_SUBTREE:
|
||||
switch ( (*msp)->ms_type ) {
|
||||
case META_ST_SUBTREE:
|
||||
if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
|
||||
metasubtree_t *tmp = *msp;
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"%s: previous rule \"dn.subtree:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n",
|
||||
log_prefix, pattern, (*msp)->ms_dn.bv_val );
|
||||
*msp = (*msp)->ms_next;
|
||||
tmp->ms_next = NULL;
|
||||
meta_subtree_destroy( tmp );
|
||||
continue;
|
||||
|
||||
} else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) ) {
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"%s: previous rule \"dn.subtree:%s\" contains rule \"dn.subtree:%s\" (ignored)\n",
|
||||
log_prefix, (*msp)->ms_dn.bv_val, pattern );
|
||||
meta_subtree_destroy( ms );
|
||||
ms = NULL;
|
||||
return( 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
case META_ST_SUBORDINATE:
|
||||
if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
|
||||
metasubtree_t *tmp = *msp;
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"%s: previous rule \"dn.children:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n",
|
||||
log_prefix, pattern, (*msp)->ms_dn.bv_val );
|
||||
*msp = (*msp)->ms_next;
|
||||
tmp->ms_next = NULL;
|
||||
meta_subtree_destroy( tmp );
|
||||
continue;
|
||||
|
||||
} else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) && ms->ms_dn.bv_len > (*msp)->ms_dn.bv_len ) {
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"%s: previous rule \"dn.children:%s\" contains rule \"dn.subtree:%s\" (ignored)\n",
|
||||
log_prefix, (*msp)->ms_dn.bv_val, pattern );
|
||||
meta_subtree_destroy( ms );
|
||||
ms = NULL;
|
||||
return( 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
case META_ST_REGEX:
|
||||
if ( regexec( &(*msp)->ms_regex, ms->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) {
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"%s: previous rule \"dn.regex:%s\" may contain rule \"dn.subtree:%s\"\n",
|
||||
log_prefix, (*msp)->ms_regex_pattern, ms->ms_dn.bv_val );
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case META_ST_SUBORDINATE:
|
||||
switch ( (*msp)->ms_type ) {
|
||||
case META_ST_SUBTREE:
|
||||
if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
|
||||
metasubtree_t *tmp = *msp;
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"%s: previous rule \"dn.children:%s\" is contained in rule \"dn.subtree:%s\" (replaced)\n",
|
||||
log_prefix, pattern, (*msp)->ms_dn.bv_val );
|
||||
*msp = (*msp)->ms_next;
|
||||
tmp->ms_next = NULL;
|
||||
meta_subtree_destroy( tmp );
|
||||
continue;
|
||||
|
||||
} else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) && ms->ms_dn.bv_len > (*msp)->ms_dn.bv_len ) {
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"%s: previous rule \"dn.children:%s\" contains rule \"dn.subtree:%s\" (ignored)\n",
|
||||
log_prefix, (*msp)->ms_dn.bv_val, pattern );
|
||||
meta_subtree_destroy( ms );
|
||||
ms = NULL;
|
||||
return( 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
case META_ST_SUBORDINATE:
|
||||
if ( dnIsSuffix( &(*msp)->ms_dn, &ms->ms_dn ) ) {
|
||||
metasubtree_t *tmp = *msp;
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"%s: previous rule \"dn.children:%s\" is contained in rule \"dn.children:%s\" (replaced)\n",
|
||||
log_prefix, pattern, (*msp)->ms_dn.bv_val );
|
||||
*msp = (*msp)->ms_next;
|
||||
tmp->ms_next = NULL;
|
||||
meta_subtree_destroy( tmp );
|
||||
continue;
|
||||
|
||||
} else if ( dnIsSuffix( &ms->ms_dn, &(*msp)->ms_dn ) ) {
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"%s: previous rule \"dn.children:%s\" contains rule \"dn.children:%s\" (ignored)\n",
|
||||
log_prefix, (*msp)->ms_dn.bv_val, pattern );
|
||||
meta_subtree_destroy( ms );
|
||||
ms = NULL;
|
||||
return( 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
case META_ST_REGEX:
|
||||
if ( regexec( &(*msp)->ms_regex, ms->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) {
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"%s: previous rule \"dn.regex:%s\" may contain rule \"dn.subtree:%s\"\n",
|
||||
log_prefix, (*msp)->ms_regex_pattern, ms->ms_dn.bv_val );
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case META_ST_REGEX:
|
||||
switch ( (*msp)->ms_type ) {
|
||||
case META_ST_SUBTREE:
|
||||
case META_ST_SUBORDINATE:
|
||||
if ( regexec( &ms->ms_regex, (*msp)->ms_dn.bv_val, 0, NULL, 0 ) == 0 ) {
|
||||
Debug( LDAP_DEBUG_CONFIG,
|
||||
"%s: previous rule \"dn.subtree:%s\" may be contained in rule \"dn.regex:%s\"\n",
|
||||
log_prefix, (*msp)->ms_dn.bv_val, ms->ms_regex_pattern );
|
||||
}
|
||||
break;
|
||||
|
||||
case META_ST_REGEX:
|
||||
/* no check possible */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
msp = &(*msp)->ms_next;
|
||||
}
|
||||
|
||||
*msp = ms;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
meta_back_db_config(
|
||||
|
|
@ -99,8 +405,7 @@ meta_back_db_config(
|
|||
const char *fname,
|
||||
int lineno,
|
||||
int argc,
|
||||
char **argv
|
||||
)
|
||||
char **argv )
|
||||
{
|
||||
metainfo_t *mi = ( metainfo_t * )be->be_private;
|
||||
|
||||
|
|
@ -315,81 +620,35 @@ meta_back_db_config(
|
|||
}
|
||||
|
||||
/* subtree-exclude */
|
||||
} else if ( strcasecmp( argv[ 0 ], "subtree-exclude" ) == 0 ) {
|
||||
int i = mi->mi_ntargets - 1;
|
||||
struct berval dn, ndn;
|
||||
} else if ( strcasecmp( argv[ 0 ], "subtree-exclude" ) == 0 ||
|
||||
strcasecmp( argv[ 0 ], "subtree-include" ) == 0)
|
||||
{
|
||||
char log_prefix[SLAP_TEXT_BUFLEN];
|
||||
char textbuf[SLAP_TEXT_BUFLEN];
|
||||
char *arg0;
|
||||
int i = mi->mi_ntargets - 1;
|
||||
|
||||
if ( i < 0 ) {
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: need \"uri\" directive first\n",
|
||||
"%s: line %d: need \"uri\" directive first\n",
|
||||
fname, lineno, 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch ( argc ) {
|
||||
case 1:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: missing DN in \"subtree-exclude <DN>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
break;
|
||||
if ( strcasecmp( argv[ 0 ], "subtree-exclude" ) == 0 ) {
|
||||
arg0 = "subtree-exclude";
|
||||
|
||||
default:
|
||||
Debug( LDAP_DEBUG_ANY,
|
||||
"%s: line %d: too many args in \"subtree-exclude <DN>\" line\n",
|
||||
fname, lineno, 0 );
|
||||
} else {
|
||||
arg0 = "subtree-include";
|
||||
}
|
||||
|
||||
snprintf( log_prefix, sizeof(log_prefix), "%s: line %d: %s", fname, lineno, arg0 );
|
||||
|
||||
if ( meta_subtree_config( mi->mi_targets[ i ], argc, argv, textbuf, sizeof(textbuf), log_prefix ) ) {
|
||||
Debug( LDAP_DEBUG_ANY, "%s: %s\n", log_prefix, textbuf, 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
ber_str2bv( argv[ 1 ], 0, 0, &dn );
|
||||
if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL )
|
||||
!= LDAP_SUCCESS )
|
||||
{
|
||||
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
|
||||
"subtree-exclude DN=\"%s\" is invalid\n",
|
||||
fname, lineno, argv[ 1 ] );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if ( !dnIsSuffix( &ndn, &mi->mi_targets[ i ]->mt_nsuffix ) ) {
|
||||
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
|
||||
"subtree-exclude DN=\"%s\" "
|
||||
"must be subtree of target\n",
|
||||
fname, lineno, argv[ 1 ] );
|
||||
ber_memfree( ndn.bv_val );
|
||||
return( 1 );
|
||||
}
|
||||
|
||||
if ( mi->mi_targets[ i ]->mt_subtree_exclude != NULL ) {
|
||||
int j;
|
||||
|
||||
for ( j = 0; !BER_BVISNULL( &mi->mi_targets[ i ]->mt_subtree_exclude[ j ] ); j++ )
|
||||
{
|
||||
if ( dnIsSuffix( &mi->mi_targets[ i ]->mt_subtree_exclude[ j ], &ndn ) ) {
|
||||
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
|
||||
"subtree-exclude DN=\"%s\" "
|
||||
"is suffix of another subtree-exclude\n",
|
||||
fname, lineno, argv[ 1 ] );
|
||||
/* reject, because it might be superior
|
||||
* to more than one subtree-exclude */
|
||||
ber_memfree( ndn.bv_val );
|
||||
return( 1 );
|
||||
|
||||
} else if ( dnIsSuffix( &ndn, &mi->mi_targets[ i ]->mt_subtree_exclude[ j ] ) ) {
|
||||
Debug( LDAP_DEBUG_ANY, "%s: line %d: "
|
||||
"another subtree-exclude is suffix of "
|
||||
"subtree-exclude DN=\"%s\"\n",
|
||||
fname, lineno, argv[ 1 ] );
|
||||
ber_memfree( ndn.bv_val );
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ber_bvarray_add( &mi->mi_targets[ i ]->mt_subtree_exclude, &ndn );
|
||||
|
||||
/* default target directive */
|
||||
} else if ( strcasecmp( argv[ 0 ], "default-target" ) == 0 ) {
|
||||
int i = mi->mi_ntargets - 1;
|
||||
|
|
@ -1564,6 +1823,7 @@ idassert-authzFrom "dn:<rootdn>"
|
|||
} else {
|
||||
return SLAP_CONF_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -318,8 +318,9 @@ target_free(
|
|||
free( mt->mt_uri );
|
||||
ldap_pvt_thread_mutex_destroy( &mt->mt_uri_mutex );
|
||||
}
|
||||
if ( mt->mt_subtree_exclude ) {
|
||||
ber_bvarray_free( mt->mt_subtree_exclude );
|
||||
if ( mt->mt_subtree ) {
|
||||
meta_subtree_destroy( mt->mt_subtree );
|
||||
mt->mt_subtree = NULL;
|
||||
}
|
||||
if ( !BER_BVISNULL( &mt->mt_psuffix ) ) {
|
||||
free( mt->mt_psuffix.bv_val );
|
||||
|
|
|
|||
Loading…
Reference in a new issue