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;
}
}
+#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 ) {
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;
}
} 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",
return rc;
}
+
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
/* 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 ) {
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 */
}
if (e) {
- int result = send_search_entry(be, conn, op,
+ result = send_search_entry(be, conn, op,
e, attrs, attrsonly, NULL);
switch (result) {
* 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 (?)
*/
#undef BACKSQL_TRACE
-
typedef struct {
char *dbhost;
int dbport;
#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"
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 );
#if 0
backsql_entry_addattr( bsi->e,
&bv_n_objectclass,
- &bsi->oc->name );
+ BACKSQL_OC_NAME( bsi->oc ) );
#endif
continue;
}
"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 );
}
}
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;
}
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;
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 );
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;
* 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;
* 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:
"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,
* 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;
}
}
* 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 );
* 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 );
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;
#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
*/
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
*/
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",
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 ? */
}
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",
"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;
}
#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 );
return res;
}
-/*
- * Deprecated
- */
backsql_oc_map_rec *
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 );
#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 );
#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;
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 );
#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 ) {
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 ) {
*/
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 */
#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 )
{
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 ];
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 "*"
*/
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;
}
bsi->status = LDAP_SUCCESS;
}
-int
+static int
backsql_process_filter_list( backsql_srch_info *bsi, Filter *f, int op )
{
int res;
return 1;
}
-int
+static int
backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f )
{
int i;
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;
case LDAP_FILTER_AND:
rc = backsql_process_filter_list( bsi, f->f_and,
- LDAP_FILTER_AND);
+ LDAP_FILTER_AND );
done = 1;
break;
ad = f->f_desc;
break;
+ case LDAP_FILTER_EXT:
+ ad = f->f_mra->ma_desc;
+ break;
+
default:
ad = f->f_av_desc;
break;
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;
}
break;
case LDAP_FILTER_GE:
+ /*
+ * FIXME: should we uppercase the operands?
+ */
backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "cblbc",
'(' /* ) */ ,
&at->sel_expr,
break;
case LDAP_FILTER_LE:
+ /*
+ * FIXME: should we uppercase the operands?
+ */
backsql_strfcat( &bsi->flt_where, &bsi->fwhere_len, "cblbc",
'(' /* ) */ ,
&at->sel_expr,
&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",
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(): "
*/
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 ) {
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++;
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 );
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,
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-
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
*/
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 ) +
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;
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 ) +
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;
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 */
+
{
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;
+
+ 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 {
- 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;
+ /*
+ * 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;
+
+ /* 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;
+ }
- rc = value_match( &ret, a->a_desc, mra->ma_rule,
- SLAP_MR_ASSERTION_SYNTAX_MATCH,
- bv, &mra->ma_value,
- &text );
+ /* normalize for equality */
+ rc = value_validate_normalize( a->a_desc,
+ SLAP_MR_EQUALITY,
+ &mra->ma_value, &value, &text );
+ if ( rc != LDAP_SUCCESS ) {
+ continue;
+ }
- if( rc != LDAP_SUCCESS ) {
- return rc;
+ /* check search access */
+ if ( !access_allowed( be, conn, op, e,
+ a->a_desc, &value, ACL_SEARCH, NULL ) ) {
+ continue;
}
- if ( ret == 0 ) {
- return LDAP_COMPARE_TRUE;
+ /* 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;
}
#include "../../libraries/liblber/lber-int.h"
-static int test_mra_vrFilter(
+static int
+test_mra_vrFilter(
Backend *be,
Connection *conn,
Operation *op,
return LDAP_SUCCESS;
}
-static int test_mra_vrFilter(
+static int
+test_mra_vrFilter(
Backend *be,
Connection *conn,
Operation *op,
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;
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 ) {
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 );
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 ) {
}
}
+ /*
+ * 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 )
mra_free( ma, 1 );
return LDAP_INAPPROPRIATE_MATCHING;
}
+#endif
- /* 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;
- }
+#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 );
+ /*
+ * 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 );
+
+ }
+#endif /* SLAP_X_MRA_MATCH_DNATTRS */
if( rc != LDAP_SUCCESS ) {
mra_free( ma, 1 );
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
*/
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 ));
}
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;
}
}
- /* 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;
"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 );
};
#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"