- added the capability to filter based on hasSubordinate attribute

to back-bdb, back-ldbm and back-sql (the latter with limitations);
- added handling of ":dn" attributes to extended rfc2254 filters
  and to matched value filter
- altered the behavior of get_mra() when a matching rule is given:
  now it checks whether it is compatible with the attribute syntax
  and, in case it is, the given mr is used.  In case of no type,
  the check is delayed when filtering
This commit is contained in:
Pierangelo Masarati 2002-08-29 10:55:48 +00:00
parent f4c5362955
commit fbc11bd16a
20 changed files with 831 additions and 149 deletions

View file

@ -59,6 +59,10 @@ bdb_search(
struct slap_limits_set *limit = NULL;
int isroot = 0;
#ifdef SLAP_X_FILTER_HASSUBORDINATES
int filter_hasSubordinates = 0;
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
u_int32_t locker;
DB_LOCK lock;
@ -322,11 +326,22 @@ dn2entry_retry:
}
}
#ifdef SLAP_X_FILTER_HASSUBORDINATES
/*
* is hasSubordinates used in the filter ?
* FIXME: we may compute this directly when parsing the filter
*/
filter_hasSubordinates = filter_has_subordinates( filter );
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
for ( id = bdb_idl_first( candidates, &cursor );
id != NOID;
id = bdb_idl_next( candidates, &cursor ) )
{
int scopeok = 0;
#ifdef SLAP_X_FILTER_HASSUBORDINATES
Attribute *hasSubordinates = NULL;
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
/* check for abandon */
if ( op->o_abandon ) {
@ -490,8 +505,47 @@ id2entry_retry:
goto loop_continue;
}
#ifdef SLAP_X_FILTER_HASSUBORDINATES
/*
* if hasSubordinates is used in the filter,
* append it to the entry's attributes
*/
if ( filter_hasSubordinates ) {
int hs;
rc = bdb_hasSubordinates( be, conn, op, e, &hs);
if ( rc != LDAP_SUCCESS ) {
goto loop_continue;
}
hasSubordinates = slap_operational_hasSubordinate( hs == LDAP_COMPARE_TRUE );
if ( hasSubordinates == NULL ) {
goto loop_continue;
}
hasSubordinates->a_next = e->e_attrs;
e->e_attrs = hasSubordinates;
}
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
/* if it matches the filter and scope, send it */
rc = test_filter( be, conn, op, e, filter );
#ifdef SLAP_X_FILTER_HASSUBORDINATES
if ( hasSubordinates ) {
/*
* FIXME: this is fairly inefficient, because
* if hasSubordinates is among the required
* attrs, it will be added again later;
* maybe we should leave it and check
* check later if it's already present,
* if required
*/
e->e_attrs = e->e_attrs->a_next;
attr_free( hasSubordinates );
}
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
if ( rc == LDAP_COMPARE_TRUE ) {
struct berval dn;
@ -557,8 +611,8 @@ id2entry_retry:
}
} else {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, RESULTS,
"bdb_search: %ld does match filter\n", (long) id, 0, 0);
LDAP_LOG ( OPERATION, RESULTS,
"bdb_search: %ld does match filter\n", (long) id, 0, 0);
#else
Debug( LDAP_DEBUG_TRACE,
"bdb_search: %ld does match filter\n",
@ -774,3 +828,4 @@ static int search_candidates(
return rc;
}

View file

@ -57,6 +57,10 @@ ldbm_back_search(
struct slap_limits_set *limit = NULL;
int isroot = 0;
#ifdef SLAP_X_FILTER_HASSUBORDINATES
int filter_hasSubordinates = 0;
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
#ifdef NEW_LOGGING
LDAP_LOG( BACK_LDBM, ENTRY, "ldbm_back_search: enter\n", 0, 0, 0 );
#else
@ -288,10 +292,22 @@ searchit:
/* compute it anyway; root does not use it */
stoptime = op->o_time + tlimit;
#ifdef SLAP_X_FILTER_HASSUBORDINATES
/*
* is hasSubordinates used in the filter ?
* FIXME: we may compute this directly when parsing the filter
*/
filter_hasSubordinates = filter_has_subordinates( filter );
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
for ( id = idl_firstid( candidates, &cursor ); id != NOID;
id = idl_nextid( candidates, &cursor ) )
{
int scopeok = 0;
int result = 0;
#ifdef SLAP_X_FILTER_HASSUBORDINATES
Attribute *hasSubordinates = NULL;
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
/* check for abandon */
if ( op->o_abandon ) {
@ -420,8 +436,44 @@ searchit:
goto loop_continue;
}
#ifdef SLAP_X_FILTER_HASSUBORDINATES
/*
* if hasSubordinates is used in the filter,
* append it to the entry's attributes
*/
if ( filter_hasSubordinates ) {
int hs;
hs = has_children( be, e );
hasSubordinates = slap_operational_hasSubordinate( hs );
if ( hasSubordinates == NULL ) {
goto loop_continue;
}
hasSubordinates->a_next = e->e_attrs;
e->e_attrs = hasSubordinates;
}
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
/* if it matches the filter and scope, send it */
if ( test_filter( be, conn, op, e, filter ) == LDAP_COMPARE_TRUE ) {
result = test_filter( be, conn, op, e, filter );
#ifdef SLAP_X_FILTER_HASSUBORDINATES
if ( hasSubordinates ) {
/*
* FIXME: this is fairly inefficient, because
* if hasSubordinates is among the required
* attrs, it will be added again later;
* maybe we should leave it and check
* check later if it's already present,
* if required
*/
e->e_attrs = e->e_attrs->a_next;
attr_free( hasSubordinates );
}
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
if ( result == LDAP_COMPARE_TRUE ) {
struct berval dn;
/* check scope */
@ -452,7 +504,7 @@ searchit:
}
if (e) {
int result = send_search_entry(be, conn, op,
result = send_search_entry(be, conn, op,
e, attrs, attrsonly, NULL);
switch (result) {

View file

@ -49,6 +49,10 @@
* statements (needed by PostgreSQL)
* - upper_needs_cast cast the argument of upper when required
* (basically when building dn substring queries)
* - added noop control
* - added values return filter control
* - hasSubordinate can be used in search filters (with limitations)
* - eliminated oc->name; use oc->oc->soc_cname instead
*
* Todo:
* - add security checks for SQL statements that can be injected (?)
@ -80,7 +84,6 @@
*/
#undef BACKSQL_TRACE
typedef struct {
char *dbhost;
int dbport;

View file

@ -14,6 +14,7 @@
#include <stdio.h>
#include <sys/types.h>
#include "ac/string.h"
#include "lber_pvt.h"
#include "ldap_pvt.h"
#include "slap.h"
#include "back-sql.h"
@ -255,8 +256,7 @@ backsql_get_attr_vals( backsql_at_map_rec *at, backsql_srch_info *bsi )
Debug( LDAP_DEBUG_TRACE, "==>backsql_get_attr_vals(): "
"oc='%s' attr='%s' keyval=%ld\n",
// bsi->oc->name.bv_val, at->name.bv_val,
bsi->oc->oc->soc_names[0], at->ad->ad_cname.bv_val,
BACKSQL_OC_NAME( bsi->oc ), at->ad->ad_cname.bv_val,
bsi->c_eid->keyval );
rc = backsql_Prepare( bsi->dbh, &sth, at->query, 0 );
@ -363,7 +363,7 @@ backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid )
#if 0
backsql_entry_addattr( bsi->e,
&bv_n_objectclass,
&bsi->oc->name );
BACKSQL_OC_NAME( bsi->oc ) );
#endif
continue;
}
@ -376,7 +376,7 @@ backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid )
"attribute '%s' is not defined "
"for objectlass '%s'\n",
attr->an_name.bv_val,
bsi->oc->name.bv_val, 0 );
BACKSQL_OC_NAME( bsi->oc ), 0 );
}
}
@ -387,7 +387,7 @@ backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid )
bsi, 0, AVL_INORDER );
}
if ( attr_merge_one( bsi->e, ad_oc, &bsi->oc->name ) ) {
if ( attr_merge_one( bsi->e, ad_oc, &bsi->oc->oc->soc_cname ) ) {
entry_free( e );
return NULL;
}
@ -396,7 +396,7 @@ backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid )
const char *text = NULL;
char textbuf[ 1024 ];
size_t textlen = sizeof( textbuf );
struct berval bv[ 2 ] = { bsi->oc->name, { 0, NULL } };
struct berval bv[ 2 ] = { bsi->oc->oc->soc_cname, BER_BVNULL };
struct berval soc;
AttributeDescription *ad_soc
= slap_schema.si_ad_structuralObjectClass;
@ -408,7 +408,7 @@ backsql_id2entry( backsql_srch_info *bsi, Entry *e, backsql_entryID *eid )
return NULL;
}
if ( bsi->attr_flags | BSQL_SF_ALL_OPER
if ( bsi->bsi_flags | BSQL_SF_ALL_OPER
|| an_find( bsi->attrs, &AllOper ) ) {
if ( attr_merge_one( bsi->e, ad_soc, &soc ) ) {
entry_free( e );

View file

@ -43,6 +43,18 @@ int
sql_back_initialize(
BackendInfo *bi )
{
static char *controls[] = {
#ifdef LDAP_CONTROL_NOOP
LDAP_CONTROL_NOOP,
#endif
#ifdef LDAP_CONTROL_VALUESRETURNFILTER
LDAP_CONTROL_VALUESRETURNFILTER,
#endif
NULL
};
bi->bi_controls = controls;
Debug( LDAP_DEBUG_TRACE,"==>backsql_initialize()\n", 0, 0, 0 );
bi->bi_open = 0;

View file

@ -549,9 +549,10 @@ backsql_modify(
* or if a single operation on an attribute fails
* for any reason
*/
SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
SQLTransact( SQL_NULL_HENV, dbh,
op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
}
send_ldap_result( conn, op, res, "", text, NULL, NULL );
send_ldap_result( conn, op, res, NULL, text, NULL, NULL );
Debug( LDAP_DEBUG_TRACE, "<==backsql_modify()\n", 0, 0, 0 );
return 0;
@ -865,7 +866,8 @@ backsql_modrdn(
* or if a single operation on an attribute fails for any
* reason
*/
SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
SQLTransact( SQL_NULL_HENV, dbh,
op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
}
modrdn_return:
@ -1239,7 +1241,7 @@ backsql_add(
"attribute '%s' is not registered "
"in objectclass '%s'\n",
at->a_desc->ad_cname.bv_val,
oc->name.bv_val, 0 );
BACKSQL_OC_NAME( oc ), 0 );
if ( BACKSQL_FAIL_IF_NO_MAPPING( bi ) ) {
send_ldap_result( conn, op,
@ -1312,7 +1314,7 @@ backsql_add(
* to build the entry
*/
if ( at->a_desc == slap_schema.si_ad_objectClass ) {
if ( ber_bvcmp( at_val, &oc->name ) == 0 ) {
if ( bvmatch( at_val, &oc->oc->soc_cname ) ) {
continue;
}
}
@ -1411,7 +1413,8 @@ backsql_add(
* or if a single operation on an attribute fails
* for any reason
*/
SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
SQLTransact( SQL_NULL_HENV, dbh,
op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
send_ldap_result( conn, op, LDAP_SUCCESS, "",
NULL, NULL, NULL );
@ -1570,7 +1573,8 @@ backsql_delete(
* or if a single operation on an attribute fails
* for any reason
*/
SQLTransact( SQL_NULL_HENV, dbh, SQL_COMMIT );
SQLTransact( SQL_NULL_HENV, dbh,
op->o_noop ? SQL_ROLLBACK : SQL_COMMIT );
send_ldap_result( conn, op, LDAP_SUCCESS, "", NULL, NULL, NULL );
Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 );

View file

@ -63,13 +63,18 @@ backsql_operational(
backsql_info *bi = (backsql_info*)be->be_private;
SQLHDBC dbh = SQL_NULL_HDBC;
Attribute **aa = a;
int rc;
int rc = 0;
Debug( LDAP_DEBUG_TRACE, "==>backsql_operational(): entry '%s'\n",
e->e_nname.bv_val, 0, 0 );
if ( opattrs || ad_inlist( slap_schema.si_ad_hasSubordinates, attrs ) ) {
if ( ( opattrs || ad_inlist( slap_schema.si_ad_hasSubordinates, attrs ) )
#ifdef SLAP_X_FILTER_HASSUBORDINATES
&& attr_find( e->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
) {
rc = backsql_get_db_conn( be, conn, &dbh );
if ( rc != LDAP_SUCCESS ) {
goto no_connection;

View file

@ -15,23 +15,13 @@
#include <sys/types.h>
#include <string.h>
#include "slap.h"
#include "lber_pvt.h"
#include "ldap_pvt.h"
#include "back-sql.h"
#include "sql-wrap.h"
#include "schema-map.h"
#include "util.h"
/*
* Deprecated
*/
#if 0
static int
backsql_cmp_oc_name( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
{
return BACKSQL_NCMP( &m1->name, &m2->name );
}
#endif
/*
* Uses the pointer to the ObjectClass structure
*/
@ -47,17 +37,6 @@ backsql_cmp_oc_id( backsql_oc_map_rec *m1, backsql_oc_map_rec *m2 )
return ( m1->id < m2->id ? -1 : ( m1->id > m2->id ? 1 : 0 ) );
}
/*
* Deprecated
*/
#if 0
static int
backsql_cmp_attr_name( backsql_at_map_rec *m1, backsql_at_map_rec *m2 )
{
return BACKSQL_NCMP( &m1->name, &m2->name );
}
#endif
/*
* Uses the pointer to the AttributeDescription structure
*/
@ -72,7 +51,7 @@ backsql_make_attr_query(
backsql_oc_map_rec *oc_map,
backsql_at_map_rec *at_map )
{
struct berval tmps = { 0, NULL };
struct berval tmps = BER_BVNULL;
ber_len_t tmpslen = 0;
backsql_strfcat( &tmps, &tmpslen, "lblblblbcbl",
@ -250,12 +229,11 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
oc_map->id = strtol( oc_row.cols[ 0 ], NULL, 0 );
ber_str2bv( oc_row.cols[ 1 ], 0, 1, &oc_map->name );
oc_map->oc = oc_bvfind( &oc_map->name );
oc_map->oc = oc_find( oc_row.cols[ 1 ] );
if ( oc_map->oc == NULL ) {
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"objectClass '%s' is not defined in schema\n",
oc_map->name.bv_val, 0, 0 );
oc_row.cols[ 1 ], 0, 0 );
return LDAP_OTHER; /* undefined objectClass ? */
}
@ -288,7 +266,7 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
oc_id = oc_map->id;
Debug( LDAP_DEBUG_TRACE, "load_schema_map(): "
"objectClass '%s': keytbl='%s' keycol='%s'\n",
oc_map->name.bv_val,
BACKSQL_OC_NAME( oc_map ),
oc_map->keytbl.bv_val, oc_map->keycol.bv_val );
if ( oc_map->create_proc ) {
Debug( LDAP_DEBUG_TRACE, "create_proc='%s'\n",
@ -349,7 +327,7 @@ backsql_load_schema_map( backsql_info *si, SQLHDBC dbh )
"attribute '%s' for objectClass '%s' "
"is not defined in schema: %s\n",
at_map->ad->ad_cname.bv_val,
oc_map->name.bv_val, text );
BACKSQL_OC_NAME( oc_map ), text );
return LDAP_CONSTRAINT_VIOLATION;
}
@ -415,7 +393,8 @@ backsql_oc2oc( backsql_info *si, ObjectClass *oc )
#ifdef BACKSQL_TRACE
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
"found name='%s', id=%d\n", res->name, res->id, 0 );
"found name='%s', id=%d\n",
BACKSQL_OC_NAME( res ), res->id, 0 );
} else {
Debug( LDAP_DEBUG_TRACE, "<==backsql_oc2oc(): "
"not found\n", 0, 0, 0 );
@ -425,9 +404,6 @@ backsql_oc2oc( backsql_info *si, ObjectClass *oc )
return res;
}
/*
* Deprecated
*/
backsql_oc_map_rec *
backsql_name2oc( backsql_info *si, struct berval *oc_name )
{
@ -449,7 +425,8 @@ backsql_name2oc( backsql_info *si, struct berval *oc_name )
#ifdef BACKSQL_TRACE
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
"found name='%s', id=%d\n", res->name, res->id, 0 );
"found name='%s', id=%d\n",
BACKSQL_OC_NAME( res ), res->id, 0 );
} else {
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
"not found\n", 0, 0, 0 );
@ -476,7 +453,8 @@ backsql_id2oc( backsql_info *si, unsigned long id )
#ifdef BACKSQL_TRACE
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
"found name='%s', id=%d\n", res->name, res->id, 0 );
"found name='%s', id=%d\n",
BACKSQL_OC_NAME( res ), res->id, 0 );
} else {
Debug( LDAP_DEBUG_TRACE, "<==oc_with_name(): "
"not found\n", 0, 0, 0 );
@ -494,7 +472,7 @@ backsql_ad2at( backsql_oc_map_rec* objclass, AttributeDescription *ad )
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>backsql_ad2at(): "
"searching for attribute '%s' for objectclass '%s'\n",
attr, objclass->name, 0 );
attr, BACKSQL_OC_NAME( objclass ), 0 );
#endif /* BACKSQL_TRACE */
tmp.ad = ad;
@ -505,7 +483,7 @@ backsql_ad2at( backsql_oc_map_rec* objclass, AttributeDescription *ad )
if ( res != NULL ) {
Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
"found name='%s', sel_expr='%s'\n",
res->name, res->sel_expr.bv_val, 0 );
res->ad->ad_cname.bv_val, res->sel_expr.bv_val, 0 );
} else {
Debug( LDAP_DEBUG_TRACE, "<==backsql_ad2at(): "
"not found\n", 0, 0, 0 );
@ -527,7 +505,7 @@ backsql_name2at( backsql_oc_map_rec* objclass, struct berval *attr )
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "==>backsql_name2at(): "
"searching for attribute '%s' for objectclass '%s'\n",
attr, objclass->name, 0 );
attr, BACKSQL_OC_NAME( objclass ), 0 );
#endif /* BACKSQL_TRACE */
if ( slap_bv2ad( attr, &tmp.ad, &text ) != LDAP_SUCCESS ) {
@ -587,9 +565,8 @@ static void
backsql_free_oc( backsql_oc_map_rec *oc )
{
Debug( LDAP_DEBUG_TRACE, "==>free_oc(): '%s'\n",
oc->name.bv_val, 0, 0 );
BACKSQL_OC_NAME( oc ), 0, 0 );
avl_free( oc->attrs, (AVL_FREE)backsql_free_attr );
ch_free( oc->name.bv_val );
ch_free( oc->keytbl.bv_val );
ch_free( oc->keycol.bv_val );
if ( oc->create_proc != NULL ) {

View file

@ -11,15 +11,12 @@
*/
typedef struct {
/*
* FIXME: we explicitly keep the objectClass name because
* the ObjectClass structure does not use bervals (yet?)
*/
struct berval name;
/*
* Structure of corresponding LDAP objectClass definition
*/
ObjectClass *oc;
#define BACKSQL_OC_NAME(ocmap) ((ocmap)->oc->soc_cname.bv_val)
struct berval keytbl;
struct berval keycol;
/* expected to return keyval of newly created entry */

View file

@ -23,6 +23,8 @@
#include "entry-id.h"
#include "util.h"
static int backsql_process_filter( backsql_srch_info *bsi, Filter *f );
static int
backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad )
{
@ -33,6 +35,15 @@ backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad )
return 1;
}
/*
* clear the list (retrieve all attrs)
*/
if ( ad == NULL ) {
ch_free( bsi->attrs );
bsi->attrs = NULL;
return 1;
}
for ( ; bsi->attrs[ n_attrs ].an_name.bv_val; n_attrs++ ) {
an = &bsi->attrs[ n_attrs ];
@ -94,12 +105,8 @@ backsql_init_search(
bsi->be = be;
bsi->conn = conn;
bsi->op = op;
bsi->attr_flags = 0;
bsi->bsi_flags = 0;
/*
* FIXME: need to discover how to deal with 1.1 (NoAttrs)
*/
/*
* handle "*"
*/
@ -114,13 +121,13 @@ backsql_init_search(
for ( p = attrs; p->an_name.bv_val; p++ ) {
/*
* ignore "+"
* ignore "1.1"; handle "+"
*/
if ( BACKSQL_NCMP( &p->an_name, &AllOper ) == 0 ) {
bsi->bsi_flags |= BSQL_SF_ALL_OPER;
continue;
} else if ( BACKSQL_NCMP( &p->an_name, &NoAttrs ) == 0 ) {
bsi->attr_flags |= BSQL_SF_ALL_OPER;
continue;
}
@ -149,7 +156,7 @@ backsql_init_search(
bsi->status = LDAP_SUCCESS;
}
int
static int
backsql_process_filter_list( backsql_srch_info *bsi, Filter *f, int op )
{
int res;
@ -195,7 +202,7 @@ backsql_process_filter_list( backsql_srch_info *bsi, Filter *f, int op )
return 1;
}
int
static int
backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f )
{
int i;
@ -301,13 +308,13 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f )
return 1;
}
int
static int
backsql_process_filter( backsql_srch_info *bsi, Filter *f )
{
backsql_at_map_rec *at;
backsql_at_map_rec oc_attr = {
slap_schema.si_ad_objectClass, BER_BVC(""), BER_BVC(""),
{ 0, NULL }, NULL, NULL, NULL };
BER_BVNULL, NULL, NULL, NULL };
AttributeDescription *ad = NULL;
int done = 0;
ber_len_t len = 0;
@ -328,7 +335,7 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
case LDAP_FILTER_AND:
rc = backsql_process_filter_list( bsi, f->f_and,
LDAP_FILTER_AND);
LDAP_FILTER_AND );
done = 1;
break;
@ -346,6 +353,10 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
ad = f->f_desc;
break;
case LDAP_FILTER_EXT:
ad = f->f_mra->ma_desc;
break;
default:
ad = f->f_av_desc;
break;
@ -360,23 +371,58 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
goto done;
}
if ( ad != slap_schema.si_ad_objectClass ) {
at = backsql_ad2at( bsi->oc, ad );
} else {
/*
* Turn structuralObjectClass into objectClass
*/
if ( ad == slap_schema.si_ad_objectClass
|| ad == slap_schema.si_ad_structuralObjectClass ) {
at = &oc_attr;
backsql_strfcat( &at->sel_expr, &len, "cbc",
'\'',
&bsi->oc->name,
&bsi->oc->oc->soc_cname,
'\'' );
#if defined(SLAP_X_FILTER_HASSUBORDINATES) || defined(SLAP_X_MRA_MATCH_DNATTRS)
} else if ( ad == slap_schema.si_ad_hasSubordinates || ad == NULL ) {
/*
* FIXME: this is not robust; e.g. a filter
* '(!(hasSubordinates=TRUE))' fails because
* in SQL it would read 'NOT (1=1)' instead
* of no condition.
* Note however that hasSubordinates is boolean,
* so a more appropriate filter would be
* '(hasSubordinates=FALSE)'
*/
backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "l",
(ber_len_t)sizeof( "1=1" ) - 1, "1=1" );
if ( ad != NULL ) {
/*
* We use this flag since we need to parse
* the filter anyway; we should have used
* the frontend API function
* filter_has_subordinates()
*/
bsi->bsi_flags |= BSQL_SF_FILTER_HASSUBORDINATE;
} else {
/*
* clear attributes to fetch, to require ALL
* and try extended match on all attributes
*/
backsql_attrlist_add( bsi, NULL );
}
goto done;
#endif /* SLAP_X_FILTER_HASSUBORDINATES || SLAP_X_MRA_MATCH_DNATTRS */
} else {
at = backsql_ad2at( bsi->oc, ad );
}
if ( at == NULL ) {
Debug( LDAP_DEBUG_TRACE, "backsql_process_filter(): "
"attribute '%s' is not defined for objectclass '%s'\n",
ad->ad_cname.bv_val, bsi->oc->name.bv_val, 0 );
ad->ad_cname.bv_val, BACKSQL_OC_NAME( bsi->oc ), 0 );
backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "l",
(ber_len_t)sizeof( " 1=0 " ) - 1, " 1=0 " );
(ber_len_t)sizeof( "1=0" ) - 1, "1=0" );
goto impossible;
}
@ -461,6 +507,9 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
break;
case LDAP_FILTER_GE:
/*
* FIXME: should we uppercase the operands?
*/
backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "cblbc",
'(' /* ) */ ,
&at->sel_expr,
@ -470,6 +519,9 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f )
break;
case LDAP_FILTER_LE:
/*
* FIXME: should we uppercase the operands?
*/
backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "cblbc",
'(' /* ) */ ,
&at->sel_expr,
@ -558,13 +610,13 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query )
&bi->strcast_func,
(ber_len_t)sizeof( "('" /* ') */ ) - 1,
"('" /* ') */ ,
&bsi->oc->name,
&bsi->oc->oc->soc_cname,
(ber_len_t)sizeof( /* (' */ "')" ) - 1,
/* (' */ "')" );
} else {
backsql_strfcat( &bsi->sel, &bsi->sel_len, "cbc",
'\'',
&bsi->oc->name,
&bsi->oc->oc->soc_cname,
'\'' );
}
backsql_strfcat( &bsi->sel, &bsi->sel_len, "l",
@ -669,7 +721,7 @@ backsql_oc_get_candidates( backsql_oc_map_rec *oc, backsql_srch_info *bsi )
int j;
Debug( LDAP_DEBUG_TRACE, "==>backsql_oc_get_candidates(): oc='%s'\n",
oc->name.bv_val, 0, 0 );
BACKSQL_OC_NAME( oc ), 0, 0 );
if ( bsi->n_candidates == -1 ) {
Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): "
@ -998,6 +1050,10 @@ backsql_search(
*/
for ( eid = srch_info.id_list; eid != NULL;
eid = backsql_free_entryID( eid, 1 ) ) {
#ifdef SLAP_X_FILTER_HASSUBORDINATES
Attribute *hasSubordinate = NULL,
*a = NULL;
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
/* check for abandon */
if ( op->o_abandon ) {
@ -1035,10 +1091,68 @@ backsql_search(
continue;
}
#ifdef SLAP_X_FILTER_HASSUBORDINATES
/*
* We use this flag since we need to parse the filter
* anyway; we should have used the frontend API function
* filter_has_subordinates()
*/
if ( srch_info.bsi_flags & BSQL_SF_FILTER_HASSUBORDINATE ) {
int rc;
rc = backsql_has_children( bi, dbh, &entry->e_nname );
switch( rc ) {
case LDAP_COMPARE_TRUE:
case LDAP_COMPARE_FALSE:
hasSubordinate = slap_operational_hasSubordinate( rc == LDAP_COMPARE_TRUE );
if ( hasSubordinate != NULL ) {
for ( a = entry->e_attrs;
a && a->a_next;
a = a->a_next );
a->a_next = hasSubordinate;
}
rc = 0;
break;
default:
Debug(LDAP_DEBUG_TRACE,
"backsql_search(): "
"has_children failed( %d)\n",
rc, 0, 0 );
rc = 1;
break;
}
if ( rc ) {
continue;
}
}
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
if ( test_filter( be, conn, op, entry, filter )
== LDAP_COMPARE_TRUE ) {
sres = send_search_entry( be, conn, op, entry,
attrs, attrsonly, NULL );
#ifdef SLAP_X_FILTER_HASSUBORDINATES
if ( hasSubordinate && !( srch_info.bsi_flags & BSQL_SF_ALL_OPER )
&& !ad_inlist( slap_schema.si_ad_hasSubordinates, attrs ) ) {
a->a_next = NULL;
attr_free( hasSubordinate );
hasSubordinate = NULL;
}
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
#if 0 /* noop is masked SLAP_CTRL_UPDATE */
if ( op->o_noop ) {
sres = 0;
} else {
#endif
sres = send_search_entry( be, conn, op, entry,
attrs, attrsonly, NULL );
#if 0
}
#endif
switch ( sres ) {
case 0:
nentries++;

View file

@ -273,7 +273,7 @@ char *
backsql_get_table_spec( char **p )
{
char *s, *q;
struct berval res = { 0, NULL };
struct berval res = BER_BVNULL;
ber_len_t res_len = 0;
assert( p );

View file

@ -42,14 +42,14 @@ typedef struct backsql_srch_info {
Connection *conn;
Operation *op;
AttributeName *attrs;
int attr_flags;
#define BSQL_SF_ALL_OPER 0x0001
int bsi_flags;
#define BSQL_SF_ALL_OPER 0x0001
#define BSQL_SF_FILTER_HASSUBORDINATE 0x0002
Entry *e;
/* 1 if the db is TimesTen; 0 if it's not */
int use_reverse_dn;
} backsql_srch_info;
int backsql_process_filter( backsql_srch_info *bsi, Filter *f );
void backsql_init_search( backsql_srch_info *bsi, backsql_info *bi,
struct berval *nbase, int scope, int slimit, int tlimit,
time_t stoptime, Filter *filter, SQLHDBC dbh,

View file

@ -22,10 +22,6 @@
const struct berval slap_empty_bv = { 0, "" };
#define SLAP_LDAPDN_PRETTY 0x1
#define SLAP_LDAPDN_MAXLEN 8192
/*
* The DN syntax-related functions take advantage of the dn representation
* handling functions ldap_str2dn/ldap_dn2str. The latter are not schema-
@ -493,6 +489,60 @@ dnPretty2(
return LDAP_SUCCESS;
}
int
dnPrettyNormalDN(
Syntax *syntax,
struct berval *val,
LDAPDN **dn,
int flags )
{
assert( val );
assert( dn );
#ifdef NEW_LOGGING
LDAP_LOG( OPERATION, ARGS, ">>> dn%sDN: <%s>\n",
flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal",
val->bv_val, 0 );
#else
Debug( LDAP_DEBUG_TRACE, ">>> dn%sDN: <%s>\n",
flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal",
val->bv_val, 0 );
#endif
if ( val->bv_len == 0 ) {
return LDAP_SUCCESS;
} else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) {
return LDAP_INVALID_SYNTAX;
} else {
int rc;
/* FIXME: should be liberal in what we accept */
rc = ldap_bv2dn( val, dn, LDAP_DN_FORMAT_LDAP );
if ( rc != LDAP_SUCCESS ) {
return LDAP_INVALID_SYNTAX;
}
assert( strlen( val->bv_val ) == val->bv_len );
/*
* Schema-aware rewrite
*/
if ( LDAPDN_rewrite( *dn, flags ) != LDAP_SUCCESS ) {
ldap_dnfree( *dn );
*dn = NULL;
return LDAP_INVALID_SYNTAX;
}
}
Debug( LDAP_DEBUG_TRACE, "<<< dn%sDN\n",
flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal",
0, 0 );
return LDAP_SUCCESS;
}
/*
* Combination of both dnPretty and dnNormalize
*/

View file

@ -744,7 +744,7 @@ filter2bv( Filter *f, struct berval *fstr )
case LDAP_FILTER_EXT:
filter_escape_value( &f->f_mr_value, &tmp );
#ifndef SLAP_X_MRA_MATCH_DNATTRS
fstr->bv_len = f->f_mr_desc->ad_cname.bv_len +
( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
@ -757,6 +757,31 @@ filter2bv( Filter *f, struct berval *fstr )
f->f_mr_rule_text.bv_len ? ":" : "",
f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
tmp.bv_val );
#else /* SLAP_X_MRA_MATCH_DNATTRS */
{
struct berval ad;
if ( f->f_mr_desc ) {
ad = f->f_mr_desc->ad_cname;
} else {
ad.bv_len = 0;
ad.bv_val = "";
}
fstr->bv_len = ad.bv_len +
( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
tmp.bv_len + ( sizeof("(:=)") - 1 );
fstr->bv_val = malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
ad.bv_val,
f->f_mr_dnattrs ? ":dn" : "",
f->f_mr_rule_text.bv_len ? ":" : "",
f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
tmp.bv_val );
}
#endif /* SLAP_X_MRA_MATCH_DNATTRS */
ber_memfree( tmp.bv_val );
break;
@ -1286,6 +1311,7 @@ simple_vrFilter2bv( ValuesReturnFilter *f, struct berval *fstr )
case LDAP_FILTER_EXT:
filter_escape_value( &f->f_mr_value, &tmp );
#ifndef SLAP_X_MRA_MATCH_DNATTRS
fstr->bv_len = f->f_mr_desc->ad_cname.bv_len +
( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
@ -1298,6 +1324,32 @@ simple_vrFilter2bv( ValuesReturnFilter *f, struct berval *fstr )
f->f_mr_rule_text.bv_len ? ":" : "",
f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
tmp.bv_val );
#else /* SLAP_X_MRA_MATCH_DNATTRS */
{
struct berval ad;
if ( f->f_mr_desc ) {
ad = f->f_mr_desc->ad_cname;
} else {
ad.bv_len = 0;
ad.bv_val = "";
}
fstr->bv_len = ad.bv_len +
( f->f_mr_dnattrs ? sizeof(":dn")-1 : 0 ) +
( f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_len+1 : 0 ) +
tmp.bv_len + ( sizeof("(:=)") - 1 );
fstr->bv_val = malloc( fstr->bv_len + 1 );
snprintf( fstr->bv_val, fstr->bv_len + 1, "(%s%s%s%s:=%s)",
ad.bv_val,
f->f_mr_dnattrs ? ":dn" : "",
f->f_mr_rule_text.bv_len ? ":" : "",
f->f_mr_rule_text.bv_len ? f->f_mr_rule_text.bv_val : "",
tmp.bv_val );
}
#endif /* SLAP_X_MRA_MATCH_DNATTRS */
ber_memfree( tmp.bv_val );
break;
@ -1514,3 +1566,92 @@ return_error:
return( LDAP_SUCCESS );
}
#ifdef SLAP_X_FILTER_HASSUBORDINATES
static int filter_has_subordinates_list(
Filter *filter );
/*
* FIXME: we could detect the need to filter
* for hasSubordinates when parsing the filter ...
*/
static int
filter_has_subordinates_list(
Filter *fl )
{
Filter *f;
for ( f = fl; f != NULL; f = f->f_next ) {
int rc;
rc = filter_has_subordinates( f );
if ( rc ) {
return rc;
}
}
return 0;
}
int
filter_has_subordinates(
Filter *f )
{
AttributeDescription *ad = NULL;
switch ( f->f_choice ) {
case LDAP_FILTER_PRESENT:
ad = f->f_desc;
break;
case LDAP_FILTER_EQUALITY:
case LDAP_FILTER_APPROX:
case LDAP_FILTER_GE:
case LDAP_FILTER_LE:
ad = f->f_ava->aa_desc;
break;
case LDAP_FILTER_SUBSTRINGS:
ad = f->f_sub_desc;
break;
case LDAP_FILTER_EXT:
/* could be null; however here it is harmless */
ad = f->f_mra->ma_desc;
break;
case LDAP_FILTER_NOT:
return filter_has_subordinates( f->f_not );
case LDAP_FILTER_AND:
return filter_has_subordinates_list( f->f_and );
case LDAP_FILTER_OR:
return filter_has_subordinates_list( f->f_or );
case SLAPD_FILTER_COMPUTED:
/*
* something wrong?
*/
return 0;
default:
/*
* this means a new type of filter has been implemented,
* which is not handled yet in this function; we should
* issue a developer's warning, e.g. an assertion
*/
assert( 0 );
return -1;
}
if ( ad == slap_schema.si_ad_hasSubordinates ) {
return 1;
}
return 0;
}
#endif /* SLAP_X_FILTER_HASSUBORDINATES */

View file

@ -215,37 +215,175 @@ static int test_mra_filter(
{
Attribute *a;
#ifndef SLAP_X_MRA_MATCH_DNATTRS
if( !access_allowed( be, conn, op, e,
mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
{
return LDAP_INSUFFICIENT_ACCESS;
}
#else /* SLAP_X_MRA_MATCH_DNATTRS */
if ( mra->ma_desc ) {
/*
* if ma_desc is available, then we're filtering for
* one attribute, and SEARCH permissions can be checked
* directly.
*/
if( !access_allowed( be, conn, op, e,
mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
{
return LDAP_INSUFFICIENT_ACCESS;
}
#endif /* SLAP_X_MRA_MATCH_DNATTRS */
for(a = attrs_find( e->e_attrs, mra->ma_desc );
a != NULL;
a = attrs_find( a->a_next, mra->ma_desc ) )
{
struct berval *bv;
for ( bv = a->a_vals; bv->bv_val != NULL; bv++ ) {
int ret;
int rc;
const char *text;
for(a = attrs_find( e->e_attrs, mra->ma_desc );
a != NULL;
a = attrs_find( a->a_next, mra->ma_desc ) )
{
struct berval *bv;
for ( bv = a->a_vals; bv->bv_val != NULL; bv++ ) {
int ret;
int rc;
const char *text;
rc = value_match( &ret, a->a_desc, mra->ma_rule,
SLAP_MR_ASSERTION_SYNTAX_MATCH,
bv, &mra->ma_value, &text );
if( rc != LDAP_SUCCESS ) {
return rc;
}
if ( ret == 0 ) {
return LDAP_COMPARE_TRUE;
}
}
}
#ifdef SLAP_X_MRA_MATCH_DNATTRS
} else {
rc = value_match( &ret, a->a_desc, mra->ma_rule,
SLAP_MR_ASSERTION_SYNTAX_MATCH,
bv, &mra->ma_value,
&text );
/*
* No attribute description: test all
*/
for ( a = e->e_attrs; a != NULL; a = a->a_next ) {
struct berval *bv, value;
const char *text = NULL;
int rc;
if( rc != LDAP_SUCCESS ) {
return rc;
/* check if matching is appropriate */
if ( strcmp( mra->ma_rule->smr_syntax->ssyn_oid,
a->a_desc->ad_type->sat_syntax->ssyn_oid ) != 0 ) {
continue;
}
if ( ret == 0 ) {
return LDAP_COMPARE_TRUE;
/* normalize for equality */
rc = value_validate_normalize( a->a_desc,
SLAP_MR_EQUALITY,
&mra->ma_value, &value, &text );
if ( rc != LDAP_SUCCESS ) {
continue;
}
/* check search access */
if ( !access_allowed( be, conn, op, e,
a->a_desc, &value, ACL_SEARCH, NULL ) ) {
continue;
}
/* check match */
for ( bv = a->a_vals; bv->bv_val != NULL; bv++ ) {
int ret;
int rc;
rc = value_match( &ret, a->a_desc, mra->ma_rule,
SLAP_MR_ASSERTION_SYNTAX_MATCH,
bv, &value, &text );
if( rc != LDAP_SUCCESS ) {
return rc;
}
if ( ret == 0 ) {
return LDAP_COMPARE_TRUE;
}
}
}
}
/* check attrs in DN AVAs if required */
if ( mra->ma_dnattrs ) {
LDAPDN *dn = NULL;
int iRDN, iAVA;
int rc;
/* parse and pretty the dn */
rc = dnPrettyDN( NULL, &e->e_name, &dn );
if ( rc != LDAP_SUCCESS ) {
return LDAP_INVALID_SYNTAX;
}
/* for each AVA of each RDN ... */
for ( iRDN = 0; dn[ 0 ][ iRDN ]; iRDN++ ) {
LDAPRDN *rdn = dn[ 0 ][ iRDN ];
for ( iAVA = 0; rdn[ 0 ][ iAVA ]; iAVA++ ) {
LDAPAVA *ava = rdn[ 0 ][ iAVA ];
struct berval *bv = &ava->la_value, value;
AttributeDescription *ad = (AttributeDescription *)ava->la_private;
int ret;
int rc;
const char *text;
assert( ad );
if ( mra->ma_desc ) {
/* have a mra type? check for subtype */
if ( !is_ad_subtype( ad, mra->ma_desc ) ) {
continue;
}
value = mra->ma_value;
} else {
const char *text = NULL;
/* check if matching is appropriate */
if ( strcmp( mra->ma_rule->smr_syntax->ssyn_oid,
ad->ad_type->sat_syntax->ssyn_oid ) != 0 ) {
continue;
}
/* normalize for equality */
rc = value_validate_normalize( ad, SLAP_MR_EQUALITY,
&mra->ma_value, &value, &text );
if ( rc != LDAP_SUCCESS ) {
continue;
}
/* check search access */
if ( !access_allowed( be, conn, op, e,
ad, &value, ACL_SEARCH, NULL ) ) {
continue;
}
}
/* check match */
rc = value_match( &ret, ad, mra->ma_rule,
SLAP_MR_ASSERTION_SYNTAX_MATCH,
bv, &value, &text );
if( rc != LDAP_SUCCESS ) {
ldap_dnfree( dn );
return rc;
}
if ( ret == 0 ) {
ldap_dnfree( dn );
return LDAP_COMPARE_TRUE;
}
}
}
}
#endif /* SLAP_X_MRA_MATCH_DNATTRS */
return LDAP_COMPARE_FALSE;
}

View file

@ -19,7 +19,8 @@
#include "../../libraries/liblber/lber-int.h"
static int test_mra_vrFilter(
static int
test_mra_vrFilter(
Backend *be,
Connection *conn,
Operation *op,
@ -342,7 +343,8 @@ test_substrings_vrFilter(
return LDAP_SUCCESS;
}
static int test_mra_vrFilter(
static int
test_mra_vrFilter(
Backend *be,
Connection *conn,
Operation *op,
@ -354,11 +356,40 @@ static int test_mra_vrFilter(
int i, j;
for ( i=0; a != NULL; a = a->a_next, i++ ) {
struct berval *bv;
struct berval *bv, value;
#ifndef SLAP_X_MRA_MATCH_DNATTRS
if ( !is_ad_subtype( a->a_desc, mra->ma_desc ) ) {
return( LDAP_SUCCESS );
}
value = mra->ma_value;
#else /* SLAP_X_MRA_MATCH_DNATTRS */
if ( mra->ma_desc ) {
if ( !is_ad_subtype( a->a_desc, mra->ma_desc ) ) {
return( LDAP_SUCCESS );
}
value = mra->ma_value;
} else {
const char *text = NULL;
/* check if matching is appropriate */
if ( strcmp( mra->ma_rule->smr_syntax->ssyn_oid,
a->a_desc->ad_type->sat_syntax->ssyn_oid ) != 0 ) {
continue;
}
/* normalize for equality */
if ( value_validate_normalize( a->a_desc,
SLAP_MR_EQUALITY,
&mra->ma_value, &value,
&text ) != LDAP_SUCCESS ) {
continue;
}
}
#endif /* SLAP_X_MRA_MATCH_DNATTRS */
for ( bv = a->a_vals, j = 0; bv->bv_val != NULL; bv++, j++ ) {
int ret;
@ -367,7 +398,7 @@ static int test_mra_vrFilter(
rc = value_match( &ret, a->a_desc, mra->ma_rule,
SLAP_MR_ASSERTION_SYNTAX_MATCH,
bv, &mra->ma_value,
bv, &value,
&text );
if( rc != LDAP_SUCCESS ) {

View file

@ -170,10 +170,15 @@ get_mra(
return SLAPD_DISCONNECT;
}
#ifndef SLAP_X_MRA_MATCH_DNATTRS
/*
* Let's try to implement it
*/
if( ma->ma_dnattrs ) {
*text = "matching with \":dn\" not supported";
return LDAP_INAPPROPRIATE_MATCHING;
}
#endif /* !SLAP_X_MRA_MATCH_DNATTRS */
if( type.bv_val != NULL ) {
rc = slap_bv2ad( &type, &ma->ma_desc, text );
@ -182,9 +187,11 @@ get_mra(
return rc;
}
#ifndef SLAP_X_MRA_MATCH_DNATTRS
} else {
*text = "matching without attribute description rule not supported";
return LDAP_INAPPROPRIATE_MATCHING;
#endif /* !SLAP_X_MRA_MATCH_DNATTRS */
}
if( ma->ma_rule_text.bv_val != NULL ) {
@ -196,6 +203,40 @@ get_mra(
}
}
/*
* FIXME: is it correct that ma->ma_rule_text, if present,
* is looked-up, checked, and then replaced by the sat_equality
* of the given attribute? I'd rather do smtg like use
* the attribute's equality rule only if no matching rule
* was given, otherwise I don't see any extension ...
*/
#if 1
if ( ma->ma_rule == NULL ) {
#ifdef SLAP_X_MRA_MATCH_DNATTRS
/*
* Need either type or rule ...
*/
if ( ma->ma_desc == NULL ) {
mra_free( ma, 1 );
*text = "matching rule not recognized";
return LDAP_INAPPROPRIATE_MATCHING;
}
#endif /* !SLAP_X_MRA_MATCH_DNATTRS */
if ( ma->ma_desc->ad_type->sat_equality != NULL &&
ma->ma_desc->ad_type->sat_equality->smr_usage & SLAP_MR_EXT )
{
/* no matching rule was provided, use the attribute's
equality rule if it supports extensible matching. */
ma->ma_rule = ma->ma_desc->ad_type->sat_equality;
} else {
mra_free( ma, 1 );
return LDAP_INAPPROPRIATE_MATCHING;
}
}
#else
if( ma->ma_desc != NULL &&
ma->ma_desc->ad_type->sat_equality != NULL &&
ma->ma_desc->ad_type->sat_equality->smr_usage & SLAP_MR_EXT )
@ -208,24 +249,38 @@ get_mra(
mra_free( ma, 1 );
return LDAP_INAPPROPRIATE_MATCHING;
}
#endif
#ifdef SLAP_X_MRA_MATCH_DNATTRS
if ( ma->ma_desc != NULL ) {
#endif /* SLAP_X_MRA_MATCH_DNATTRS */
/* check to see if the matching rule is appropriate for
the syntax of the attribute. This check will need
to be extended to support other kinds of extensible
matching rules */
if( strcmp( ma->ma_rule->smr_syntax->ssyn_oid,
ma->ma_desc->ad_type->sat_syntax->ssyn_oid ) != 0 )
{
mra_free( ma, 1 );
return LDAP_INAPPROPRIATE_MATCHING;
}
/*
* OK, if no matching rule, normalize for equality, otherwise
* normalize for the matching rule.
*/
rc = value_validate_normalize( ma->ma_desc, SLAP_MR_EQUALITY,
&value, &ma->ma_value, text );
#ifdef SLAP_X_MRA_MATCH_DNATTRS
} else {
/*
* Need to normalize, but how?
*/
ma->ma_value = value;
rc = value_validate( ma->ma_rule, &ma->ma_value, text );
/* check to see if the matching rule is appropriate for
the syntax of the attribute. This check will need
to be extended to support other kinds of extensible
matching rules */
if( strcmp( ma->ma_rule->smr_syntax->ssyn_oid,
ma->ma_desc->ad_type->sat_syntax->ssyn_oid ) != 0 )
{
mra_free( ma, 1 );
return LDAP_INAPPROPRIATE_MATCHING;
}
/*
* OK, if no matching rule, normalize for equality, otherwise
* normalize for the matching rule.
*/
rc = value_validate_normalize( ma->ma_desc, SLAP_MR_EQUALITY,
&value, &ma->ma_value, text );
#endif /* SLAP_X_MRA_MATCH_DNATTRS */
if( rc != LDAP_SUCCESS ) {
mra_free( ma, 1 );

View file

@ -395,6 +395,13 @@ LDAP_SLAPD_F (int) dnX509normalize LDAP_P(( void *x509_name, struct berval *out
LDAP_SLAPD_F (int) dnX509peerNormalize LDAP_P(( void *ssl, struct berval *dn ));
LDAP_SLAPD_F (int) dnPrettyNormalDN LDAP_P(( Syntax *syntax, struct berval *val, LDAPDN **dn, int flags ));
#define dnPrettyDN(syntax, val, dn) \
dnPrettyNormalDN((syntax),(val),(dn), SLAP_LDAPDN_PRETTY)
#define dnNormalDN(syntax, val, dn) \
dnPrettyNormalDN((syntax),(val),(dn), 0)
/*
* entry.c
*/
@ -451,17 +458,31 @@ LDAP_SLAPD_F (int) get_filter LDAP_P((
LDAP_SLAPD_F (void) filter_free LDAP_P(( Filter *f ));
LDAP_SLAPD_F (void) filter2bv LDAP_P(( Filter *f, struct berval *bv ));
LDAP_SLAPD_F (int) get_vrFilter( Connection *conn, BerElement *ber,
LDAP_SLAPD_F (int) get_vrFilter LDAP_P(( Connection *conn, BerElement *ber,
ValuesReturnFilter **f,
const char **text );
const char **text ));
LDAP_SLAPD_F (void) vrFilter_free( ValuesReturnFilter *f );
LDAP_SLAPD_F (void) vrFilter2bv( ValuesReturnFilter *f, struct berval *fstr );
LDAP_SLAPD_F (void) vrFilter_free LDAP_P(( ValuesReturnFilter *f ));
LDAP_SLAPD_F (void) vrFilter2bv LDAP_P(( ValuesReturnFilter *f, struct berval *fstr ));
/*
* define to honor hasSubordinates operational attribute in search filters
*/
#define SLAP_X_FILTER_HASSUBORDINATES
#ifdef SLAP_X_FILTER_HASSUBORDINATES
LDAP_SLAPD_F (int) filter_has_subordinates LDAP_P(( Filter *filter ));
#endif /* SLAP_X_FILTER_HASSUBORDINATES */
/*
* filterentry.c
*/
/*
* define to enable dn components match in extended filter matching
*/
#define SLAP_X_MRA_MATCH_DNATTRS
LDAP_SLAPD_F (int) test_filter LDAP_P((
Backend *be, Connection *conn, Operation *op,
Entry *e, Filter *f ));

View file

@ -770,6 +770,7 @@ send_search_entry(
}
e_flags = ch_calloc ( 1, i * sizeof(char *) + k );
a_flags = (char *)(e_flags + i);
memset( a_flags, 0, k );
for ( a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
e_flags[i] = a_flags;
@ -909,25 +910,45 @@ send_search_entry(
}
}
/* free e_flags */
if ( e_flags ) {
free( e_flags );
e_flags = NULL;
}
/* eventually will loop through generated operational attributes */
/* only have subschemaSubentry implemented */
aa = backend_operational( be, conn, op, e, attrs, opattrs );
if ( aa != NULL && op->vrFilter != NULL ) {
int k = 0;
char *a_flags;
char *a_flags, **tmp;
for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
for ( j = 0; a->a_vals[j].bv_val != NULL; j++ ) k++;
}
e_flags = ch_calloc ( 1, i * sizeof(char *) + k );
/*
* Reuse previous memory - we likely need less space
* for operational attributes
*/
tmp = ch_realloc ( e_flags, i * sizeof(char *) + k );
if ( tmp == NULL ) {
#ifdef NEW_LOGGING
LDAP_LOG( OPERATION, ERR,
"send_search_entry: conn %lu "
"not enough memory "
"for matched values filtering\n",
conn ? conn->c_connid : 0, 0, 0);
#else
Debug( LDAP_DEBUG_ANY,
"send_search_entry: conn %lu "
"not enough memory "
"for matched values filtering\n",
conn ? conn->c_connid : 0, 0, 0 );
#endif
ber_free( ber, 1 );
send_ldap_result( conn, op, LDAP_NO_MEMORY,
NULL, NULL, NULL, NULL );
goto error_return;
}
e_flags = tmp;
a_flags = (char *)(e_flags + i);
memset( a_flags, 0, k );
for ( a = aa, i=0; a != NULL; a = a->a_next, i++ ) {
for ( j = 0; a->a_vals[j].bv_val != NULL; j++ );
e_flags[i] = a_flags;
@ -942,7 +963,7 @@ send_search_entry(
"matched values filtering failed\n",
conn ? conn->c_connid : 0, 0, 0);
#else
Debug( LDAP_DEBUG_ANY,
Debug( LDAP_DEBUG_ANY,
"matched values filtering failed\n", 0, 0, 0 );
#endif
ber_free( ber, 1 );

View file

@ -1683,6 +1683,12 @@ enum {
};
#endif /* SLAPD_MONITOR */
/*
* Better know these all around slapd
*/
#define SLAP_LDAPDN_PRETTY 0x1
#define SLAP_LDAPDN_MAXLEN 8192
LDAP_END_DECL
#include "proto-slap.h"