mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
add optional URI to allow restricting the scope of application of a specific dynamic list expansion rule (ITS#5761)
This commit is contained in:
parent
363f75ca5f
commit
09cb340f67
@ -50,14 +50,19 @@ occurrences, and it must appear after the
|
||||
.B overlay
|
||||
directive.
|
||||
.TP
|
||||
.B dynlist-attrset <group-oc> <URL-ad> [[<mapped-ad>:]<member-ad> ...]
|
||||
.B dynlist-attrset <group-oc> [<URI>] <URL-ad> [[<mapped-ad>:]<member-ad> ...]
|
||||
The value
|
||||
.B <group-oc>
|
||||
.B group-oc
|
||||
is the name of the objectClass that triggers the dynamic expansion of the
|
||||
data.
|
||||
|
||||
The optional
|
||||
.B URI
|
||||
restricts expansion only to entries matching the \fIDN\fP,
|
||||
the \fIscope\fP and the \fIfilter\fP portions of the URI.
|
||||
|
||||
The value
|
||||
.B <URL-ad>
|
||||
.B URL-ad
|
||||
is the name of the attributeDescription that contains the URI that is
|
||||
expanded by the overlay; if none is present, no expansion occurs.
|
||||
If the intersection of the attributes requested by the search operation
|
||||
@ -66,30 +71,32 @@ in the URI is empty, no expansion occurs for that specific URI.
|
||||
It must be a subtype of \fIlabeledURI\fP.
|
||||
|
||||
The value
|
||||
.B <member-ad>
|
||||
.B member-ad
|
||||
is optional; if present, the overlay behaves as a dynamic group: this
|
||||
attribute will list the DN of the entries resulting from the internal search.
|
||||
In this case, the <attrs> portion of the URI must be absent, and the DNs
|
||||
of all the entries resulting from the expansion of the URI are listed
|
||||
In this case, the \fIattrs\fP portion of the URIs in the
|
||||
.B URL-ad
|
||||
attribute must be absent, and the \fIDN\fPs
|
||||
of all the entries resulting from the expansion of the URIs are listed
|
||||
as values of this attribute.
|
||||
Compares that assert the value of the
|
||||
.B <member-ad>
|
||||
.B member-ad
|
||||
attribute of entries with
|
||||
.B <group-oc>
|
||||
.B group-oc
|
||||
objectClass apply as if the DN of the entries resulting from the expansion
|
||||
of the URI were present in the
|
||||
.B <group-oc>
|
||||
.B group-oc
|
||||
entry as values of the
|
||||
.B <member-ad>
|
||||
.B member-ad
|
||||
attribute.
|
||||
|
||||
Alternatively,
|
||||
.B <mapped-ad>:<member-ad>
|
||||
.B mapped-ad
|
||||
can be used to remap attributes obtained through expansion.
|
||||
.B <member-ad>
|
||||
.B member-ad
|
||||
attributes are not filled by expanded DN, but are remapped as
|
||||
.B <mapped-ad>
|
||||
attributes. Multiple mapping statements can be used.
|
||||
.B mapped-ad
|
||||
attributes. Multiple mapping statements can be used.
|
||||
|
||||
.LP
|
||||
The dynlist overlay may be used with any backend, but it is mainly
|
||||
@ -100,15 +107,26 @@ later on in the overlay stack.
|
||||
|
||||
.SH AUTHORIZATION
|
||||
By default the expansions are performed using the identity of the current
|
||||
LDAP user. This identity may be overridden by setting the
|
||||
LDAP user.
|
||||
This identity may be overridden by setting the
|
||||
.B dgIdentity
|
||||
attribute to the DN of another LDAP user. In that case the dgIdentity
|
||||
will be used when expanding the URIs in the object. Setting the dgIdentity
|
||||
to a zero-length string will cause the expansions to be performed
|
||||
anonymously. Note that the dgIdentity attribute is defined in the
|
||||
attribute in the group's entry to the DN of another LDAP user.
|
||||
In that case the dgIdentity will be used when expanding the URIs in the object.
|
||||
Setting the dgIdentity to a zero-length string will cause the expansions
|
||||
to be performed anonymously.
|
||||
Note that the dgIdentity attribute is defined in the
|
||||
.B dyngroup
|
||||
schema, and this schema must be loaded before the dgIdentity
|
||||
authorization feature may be used.
|
||||
If the
|
||||
.B dgAuthz
|
||||
attribute is also present in the group's entry, its values are used
|
||||
to determine what identities are authorized to use the
|
||||
.B dgIdentity
|
||||
to expand the group.
|
||||
Values of the
|
||||
.B dgAuthz
|
||||
attribute must conform to the (experimental) \fIOpenLDAP authz\fP syntax.
|
||||
|
||||
.SH EXAMPLE
|
||||
This example collects all the email addresses of a database into a single
|
||||
|
@ -62,21 +62,25 @@ static AttributeName *slap_anlist_no_attrs = anlist_no_attrs;
|
||||
static AttributeDescription *ad_dgIdentity, *ad_dgAuthz;
|
||||
|
||||
typedef struct dynlist_map_t {
|
||||
AttributeDescription *dlm_member_ad;
|
||||
AttributeDescription *dlm_mapped_ad;
|
||||
struct dynlist_map_t *dlm_next;
|
||||
AttributeDescription *dlm_member_ad;
|
||||
AttributeDescription *dlm_mapped_ad;
|
||||
struct dynlist_map_t *dlm_next;
|
||||
} dynlist_map_t;
|
||||
|
||||
typedef struct dynlist_info_t {
|
||||
ObjectClass *dli_oc;
|
||||
AttributeDescription *dli_ad;
|
||||
struct dynlist_map_t *dli_dlm;
|
||||
struct berval dli_uri;
|
||||
LDAPURLDesc *dli_lud;
|
||||
struct berval dli_uri_nbase;
|
||||
Filter *dli_uri_filter;
|
||||
struct berval dli_default_filter;
|
||||
struct dynlist_info_t *dli_next;
|
||||
} dynlist_info_t;
|
||||
|
||||
#define DYNLIST_USAGE \
|
||||
"\"dynlist-attrset <oc> <URL-ad> [[<mapped-ad>:]<member-ad> ...]\": "
|
||||
"\"dynlist-attrset <oc> [uri] <URL-ad> [[<mapped-ad>:]<member-ad> ...]\": "
|
||||
|
||||
static dynlist_info_t *
|
||||
dynlist_is_dynlist_next( Operation *op, SlapReply *rs, dynlist_info_t *old_dli )
|
||||
@ -102,6 +106,56 @@ dynlist_is_dynlist_next( Operation *op, SlapReply *rs, dynlist_info_t *old_dli )
|
||||
}
|
||||
|
||||
for ( ; dli; dli = dli->dli_next ) {
|
||||
if ( dli->dli_lud != NULL ) {
|
||||
/* check base and scope */
|
||||
if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) {
|
||||
int d = rs->sr_entry->e_nname.bv_len - dli->dli_uri_nbase.bv_len;
|
||||
|
||||
if ( d < 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !dnIsSuffix( &rs->sr_entry->e_nname, &dli->dli_uri_nbase ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ( dli->dli_lud->lud_scope ) {
|
||||
case LDAP_SCOPE_BASE:
|
||||
if ( d != 0 ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case LDAP_SCOPE_ONELEVEL: {
|
||||
struct berval pdn;
|
||||
|
||||
dnParent( &rs->sr_entry->e_nname, &pdn );
|
||||
if ( pdn.bv_len != dli->dli_uri_nbase.bv_len ) {
|
||||
continue;
|
||||
}
|
||||
} break;
|
||||
|
||||
case LDAP_SCOPE_SUBORDINATE:
|
||||
if ( d == 0 ) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case LDAP_SCOPE_SUBTREE:
|
||||
case LDAP_SCOPE_DEFAULT:
|
||||
break;
|
||||
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* check filter */
|
||||
if ( dli->dli_uri_filter && test_filter( op, rs->sr_entry, dli->dli_uri_filter ) != LDAP_COMPARE_TRUE ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( attr_valfind( a,
|
||||
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
|
||||
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
|
||||
@ -1143,9 +1197,9 @@ static ConfigDriver dl_cfgen;
|
||||
|
||||
/* XXXmanu 255 is the maximum arguments we allow. Can we go beyond? */
|
||||
static ConfigTable dlcfg[] = {
|
||||
{ "dynlist-attrset", "group-oc> <URL-ad> <member-ad",
|
||||
3, 255, 0, ARG_MAGIC|DL_ATTRSET, dl_cfgen,
|
||||
"( OLcfgOvAt:8.1 NAME 'olcDLattrSet' "
|
||||
{ "dynlist-attrset", "group-oc> [uri] <URL-ad> <[mapped:]member-ad> [...]",
|
||||
3, 0, 0, ARG_MAGIC|DL_ATTRSET, dl_cfgen,
|
||||
"( OLcfgOvAt:8.1 NAME 'olcDlAttrSet' "
|
||||
"DESC 'Dynamic list: <group objectClass>, <URL attributeDescription>, <member attributeDescription>' "
|
||||
"EQUALITY caseIgnoreMatch "
|
||||
"SYNTAX OMsDirectoryString "
|
||||
@ -1191,9 +1245,21 @@ dl_cfgen( ConfigArgs *c )
|
||||
assert( dli->dli_oc != NULL );
|
||||
assert( dli->dli_ad != NULL );
|
||||
|
||||
/* FIXME: check buffer overflow! */
|
||||
ptr += snprintf( c->cr_msg, sizeof( c->cr_msg ),
|
||||
SLAP_X_ORDERED_FMT "%s %s", i,
|
||||
dli->dli_oc->soc_cname.bv_val,
|
||||
SLAP_X_ORDERED_FMT "%s", i,
|
||||
dli->dli_oc->soc_cname.bv_val );
|
||||
|
||||
if ( !BER_BVISNULL( &dli->dli_uri ) ) {
|
||||
*ptr++ = ' ';
|
||||
*ptr++ = '"';
|
||||
ptr = lutil_strncopy( ptr, dli->dli_uri.bv_val,
|
||||
dli->dli_uri.bv_len );
|
||||
*ptr++ = '"';
|
||||
}
|
||||
|
||||
*ptr++ = ' ';
|
||||
ptr = lutil_strncopy( ptr, dli->dli_oc->soc_cname.bv_val,
|
||||
dli->dli_ad->ad_cname.bv_val );
|
||||
|
||||
for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) {
|
||||
@ -1238,6 +1304,22 @@ dl_cfgen( ConfigArgs *c )
|
||||
|
||||
dli_next = dli->dli_next;
|
||||
|
||||
if ( !BER_BVISNULL( &dli->dli_uri ) ) {
|
||||
ch_free( dli->dli_uri.bv_val );
|
||||
}
|
||||
|
||||
if ( dli->dli_lud != NULL ) {
|
||||
ldap_free_urldesc( dli->dli_lud );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) {
|
||||
ber_memfree( dli->dli_uri_nbase.bv_val );
|
||||
}
|
||||
|
||||
if ( dli->dli_uri_filter != NULL ) {
|
||||
filter_free( dli->dli_uri_filter );
|
||||
}
|
||||
|
||||
ch_free( dli->dli_default_filter.bv_val );
|
||||
|
||||
while ( dlm != NULL ) {
|
||||
@ -1266,6 +1348,23 @@ dl_cfgen( ConfigArgs *c )
|
||||
|
||||
dli = *dlip;
|
||||
*dlip = dli->dli_next;
|
||||
|
||||
if ( !BER_BVISNULL( &dli->dli_uri ) ) {
|
||||
ch_free( dli->dli_uri.bv_val );
|
||||
}
|
||||
|
||||
if ( dli->dli_lud != NULL ) {
|
||||
ldap_free_urldesc( dli->dli_lud );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) {
|
||||
ber_memfree( dli->dli_uri_nbase.bv_val );
|
||||
}
|
||||
|
||||
if ( dli->dli_uri_filter != NULL ) {
|
||||
filter_free( dli->dli_uri_filter );
|
||||
}
|
||||
|
||||
ch_free( dli->dli_default_filter.bv_val );
|
||||
|
||||
dlm = dli->dli_dlm;
|
||||
@ -1299,6 +1398,11 @@ dl_cfgen( ConfigArgs *c )
|
||||
*dli_next = NULL;
|
||||
ObjectClass *oc = NULL;
|
||||
AttributeDescription *ad = NULL;
|
||||
int attridx = 2;
|
||||
LDAPURLDesc *lud = NULL;
|
||||
struct berval nbase = BER_BVNULL;
|
||||
Filter *filter = NULL;
|
||||
struct berval uri = BER_BVNULL;
|
||||
dynlist_map_t *dlm = NULL;
|
||||
const char *text;
|
||||
|
||||
@ -1312,11 +1416,98 @@ dl_cfgen( ConfigArgs *c )
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = slap_str2ad( c->argv[ 2 ], &ad, &text );
|
||||
if ( strncasecmp( c->argv[ attridx ], "ldap://", STRLENOF("ldap://") ) == 0 ) {
|
||||
if ( ldap_url_parse( c->argv[ attridx ], &lud ) != LDAP_URL_SUCCESS ) {
|
||||
snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
|
||||
"unable to parse URI \"%s\"",
|
||||
c->argv[ attridx ] );
|
||||
rc = 1;
|
||||
goto done_uri;
|
||||
}
|
||||
|
||||
if ( lud->lud_host != NULL ) {
|
||||
if ( lud->lud_host[0] == '\0' ) {
|
||||
ch_free( lud->lud_host );
|
||||
lud->lud_host = NULL;
|
||||
|
||||
} else {
|
||||
snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
|
||||
"host not allowed in URI \"%s\"",
|
||||
c->argv[ attridx ] );
|
||||
rc = 1;
|
||||
goto done_uri;
|
||||
}
|
||||
}
|
||||
|
||||
if ( lud->lud_attrs != NULL ) {
|
||||
snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
|
||||
"attrs not allowed in URI \"%s\"",
|
||||
c->argv[ attridx ] );
|
||||
rc = 1;
|
||||
goto done_uri;
|
||||
}
|
||||
|
||||
if ( lud->lud_exts != NULL ) {
|
||||
snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
|
||||
"extensions not allowed in URI \"%s\"",
|
||||
c->argv[ attridx ] );
|
||||
rc = 1;
|
||||
goto done_uri;
|
||||
}
|
||||
|
||||
if ( lud->lud_dn != NULL && lud->lud_dn[ 0 ] != '\0' ) {
|
||||
struct berval dn;
|
||||
ber_str2bv( lud->lud_dn, 0, 0, &dn );
|
||||
rc = dnNormalize( 0, NULL, NULL, &dn, &nbase, NULL );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
|
||||
"DN normalization failed in URI \"%s\"",
|
||||
c->argv[ attridx ] );
|
||||
goto done_uri;
|
||||
}
|
||||
}
|
||||
|
||||
if ( lud->lud_filter != NULL && lud->lud_filter[ 0 ] != '\0' ) {
|
||||
filter = str2filter( lud->lud_filter );
|
||||
if ( filter == NULL ) {
|
||||
snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
|
||||
"filter parsing failed in URI \"%s\"",
|
||||
c->argv[ attridx ] );
|
||||
rc = 1;
|
||||
goto done_uri;
|
||||
}
|
||||
}
|
||||
|
||||
ber_str2bv( c->argv[ attridx ], 0, 1, &uri );
|
||||
|
||||
done_uri:;
|
||||
if ( rc ) {
|
||||
if ( lud ) {
|
||||
ldap_free_urldesc( lud );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &nbase ) ) {
|
||||
ber_memfree( nbase.bv_val );
|
||||
}
|
||||
|
||||
if ( filter != NULL ) {
|
||||
filter_free( filter );
|
||||
}
|
||||
|
||||
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
|
||||
c->log, c->cr_msg, 0 );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
attridx++;
|
||||
}
|
||||
|
||||
rc = slap_str2ad( c->argv[ attridx ], &ad, &text );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
|
||||
"unable to find AttributeDescription \"%s\"",
|
||||
c->argv[ 2 ] );
|
||||
c->argv[ attridx ] );
|
||||
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
|
||||
c->log, c->cr_msg, 0 );
|
||||
return 1;
|
||||
@ -1326,13 +1517,15 @@ dl_cfgen( ConfigArgs *c )
|
||||
snprintf( c->cr_msg, sizeof( c->cr_msg ), DYNLIST_USAGE
|
||||
"AttributeDescription \"%s\" "
|
||||
"must be a subtype of \"labeledURI\"",
|
||||
c->argv[ 2 ] );
|
||||
c->argv[ attridx ] );
|
||||
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
|
||||
c->log, c->cr_msg, 0 );
|
||||
return 1;
|
||||
}
|
||||
|
||||
for ( i = 3; i < c->argc; i++ ) {
|
||||
attridx++;
|
||||
|
||||
for ( i = attridx; i < c->argc; i++ ) {
|
||||
char *arg;
|
||||
char *cp;
|
||||
AttributeDescription *member_ad = NULL;
|
||||
@ -1419,6 +1612,11 @@ dl_cfgen( ConfigArgs *c )
|
||||
(*dlip)->dli_dlm = dlm;
|
||||
(*dlip)->dli_next = dli_next;
|
||||
|
||||
(*dlip)->dli_lud = lud;
|
||||
(*dlip)->dli_uri_nbase = nbase;
|
||||
(*dlip)->dli_uri_filter = filter;
|
||||
(*dlip)->dli_uri = uri;
|
||||
|
||||
rc = dynlist_build_def_filter( *dlip );
|
||||
|
||||
} break;
|
||||
@ -1625,7 +1823,24 @@ dynlist_db_destroy(
|
||||
|
||||
dli_next = dli->dli_next;
|
||||
|
||||
if ( !BER_BVISNULL( &dli->dli_uri ) ) {
|
||||
ch_free( dli->dli_uri.bv_val );
|
||||
}
|
||||
|
||||
if ( dli->dli_lud != NULL ) {
|
||||
ldap_free_urldesc( dli->dli_lud );
|
||||
}
|
||||
|
||||
if ( !BER_BVISNULL( &dli->dli_uri_nbase ) ) {
|
||||
ber_memfree( dli->dli_uri_nbase.bv_val );
|
||||
}
|
||||
|
||||
if ( dli->dli_uri_filter != NULL ) {
|
||||
filter_free( dli->dli_uri_filter );
|
||||
}
|
||||
|
||||
ch_free( dli->dli_default_filter.bv_val );
|
||||
|
||||
dlm = dli->dli_dlm;
|
||||
while ( dlm != NULL ) {
|
||||
dlm_next = dlm->dlm_next;
|
||||
|
Loading…
Reference in New Issue
Block a user