Project_Dep_Name testavl
End Project Dependency
Begin Project Dependency
- Project_Dep_Name ud
- End Project Dependency
- Begin Project Dependency
Project_Dep_Name slapcat
End Project Dependency
Begin Project Dependency
Begin Project Dependency
Project_Dep_Name ftest
End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name ldapwhoami
+ End Project Dependency
}}}
###############################################################################
###############################################################################
+Project: "ldapwhoami"=..\clients\tools\ldapwhoami.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name liblber
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libldap
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name liblutil
+ End Project Dependency
+}}}
+
+###############################################################################
+
Project: "libavl"=..\libraries\libavl\libavl.dsp - Package Owner=<4>
Package=<5>
###############################################################################
-Project: "ud"=..\clients\ud\ud.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
- Begin Project Dependency
- Project_Dep_Name libldap
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name liblber
- End Project Dependency
- Begin Project Dependency
- Project_Dep_Name liblutil
- End Project Dependency
-}}}
-
-###############################################################################
-
Global:
Package=<5>
Large projects
--------------
Redesign slapd memory allocation fault handling
-Perform a security audit (and fix any hole found)
+Update to latest autoconf and friends
Implement localization
Implement Proxy Authorization Control extension
Implement LDAP Cancel extension
Implement authPassword (RFC 3112)
-Update to latest autoconf and friends
+Populate matchingRuleUse attribute in the subschema
Small projects
--------------
Add dumpasn1 logging support
Add LDIFv1 control support
-Populate matchingRuleUse attribute in the subschema
Implement -V version options
-Add No-Op Control support to client tools (e.g. ldapsearch(1))
Add tests to test suite (ACI, moddn, manageDSAit, etc.)
Recode linked-list structs to use <ldap_queue.h> macros
Create ldapbind(1) to support bind operations
buf_out->buf_end = buf_out->buf_ptr = 0;
}
- if ( (ber_len_t)ret < to_go ) {
- /* not enough data, so pretend no data was sent. */
- return -1;
- }
-
return ret;
}
}
if ( lr != NULL ) {
- if ( sendabandon ) {
+ if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) {
ldap_free_connection( ld, lr->lr_conn, 0, 1 );
}
if ( origid == msgid ) {
/* Are there anything left in the buffer? */
if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) {
ret = ber_pvt_sb_do_write( sbiod, &p->buf_out );
- if ( ret <= 0 )
+ if ( ret < 0 )
return ret;
+ /* Still have something left?? */
+ if ( p->buf_out.buf_ptr != p->buf_out.buf_end ) {
+ errno = EWOULDBLOCK;
+ return 0;
+ }
}
/* now encode the next packet. */
}
#ifdef LDAP_R_COMPILE
+#define LDAP_DEBUG_R_SASL
void *ldap_pvt_sasl_mutex_new(void)
{
ldap_pvt_thread_mutex_t *mutex;
if ( ldap_pvt_thread_mutex_init( mutex ) == 0 ) {
return mutex;
}
+#ifndef LDAP_DEBUG_R_SASL
+ assert( 0 );
+#endif /* !LDAP_DEBUG_R_SASL */
return NULL;
}
int ldap_pvt_sasl_mutex_lock(void *mutex)
{
+#ifdef LDAP_DEBUG_R_SASL
+ if ( mutex == NULL ) {
+ return SASL_OK;
+ }
+#else /* !LDAP_DEBUG_R_SASL */
+ assert( mutex );
+#endif /* !LDAP_DEBUG_R_SASL */
return ldap_pvt_thread_mutex_lock( (ldap_pvt_thread_mutex_t *)mutex )
? SASL_FAIL : SASL_OK;
}
int ldap_pvt_sasl_mutex_unlock(void *mutex)
{
+#ifdef LDAP_DEBUG_R_SASL
+ if ( mutex == NULL ) {
+ return SASL_OK;
+ }
+#else /* !LDAP_DEBUG_R_SASL */
+ assert( mutex );
+#endif /* !LDAP_DEBUG_R_SASL */
return ldap_pvt_thread_mutex_unlock( (ldap_pvt_thread_mutex_t *)mutex )
? SASL_FAIL : SASL_OK;
}
void ldap_pvt_sasl_mutex_dispose(void *mutex)
{
+#ifdef LDAP_DEBUG_R_SASL
+ if ( mutex == NULL ) {
+ return;
+ }
+#else /* !LDAP_DEBUG_R_SASL */
+ assert( mutex );
+#endif /* !LDAP_DEBUG_R_SASL */
(void) ldap_pvt_thread_mutex_destroy( (ldap_pvt_thread_mutex_t *)mutex );
LDAP_FREE( mutex );
}
*/
#ifdef NEW_LOGGING
- LDAP_LOG ( FILTER, ARGS, "ldap_pvt_put_vrFilter: \"%s\"\n",
- str_in, 0, 0 );
+ LDAP_LOG ( FILTER, ARGS, "put_vrFilter: \"%s\"\n", str_in, 0, 0 );
#else
Debug( LDAP_DEBUG_TRACE, "put_vrFilter: \"%s\"\n", str_in, 0, 0 );
#endif
case /*'('*/ ')':
#ifdef NEW_LOGGING
- LDAP_LOG ( FILTER, DETAIL1, "ldap_pvt_put_filter: end\n", 0, 0, 0 );
+ LDAP_LOG ( FILTER, DETAIL1, "put_vrFilter: end\n", 0, 0, 0 );
#else
- Debug( LDAP_DEBUG_TRACE, "put_filter: end\n",
+ Debug( LDAP_DEBUG_TRACE, "put_vrFilter: end\n",
0, 0, 0 );
#endif
if ( ber_printf( ber, /*"["*/ "]" ) == -1 ) {
default: /* assume it's a simple type=value filter */
#ifdef NEW_LOGGING
- LDAP_LOG ( FILTER, DETAIL1, "ldap_pvt_put_filter: default\n",
+ LDAP_LOG ( FILTER, DETAIL1, "put_vrFilter: default\n",
0, 0, 0 );
#else
- Debug( LDAP_DEBUG_TRACE, "put_filter: default\n",
+ Debug( LDAP_DEBUG_TRACE, "put_vrFilter: default\n",
0, 0, 0 );
#endif
next = strchr( str, '\0' );
LDAP_F (int) ldap_chase_v3referrals( LDAP *ld, LDAPRequest *lr,
char **refs, int sref, char **referralsp, int *hadrefp );
LDAP_F (int) ldap_append_referral( LDAP *ld, char **referralsp, char *s );
+LDAP_F (int) ldap_int_flush_request( LDAP *ld, LDAPRequest *lr );
/*
* in result.c:
}
+int
+ldap_int_flush_request(
+ LDAP *ld,
+ LDAPRequest *lr
+)
+{
+ LDAPConn *lc = lr->lr_conn;
+
+ if ( ber_flush( lc->lconn_sb, lr->lr_ber, 0 ) != 0 ) {
+ if ( errno == EWOULDBLOCK ) {
+ /* need to continue write later */
+ lr->lr_status = LDAP_REQST_WRITING;
+ ldap_mark_select_write( ld, lc->lconn_sb );
+ ld->ld_errno = LDAP_BUSY;
+ return -2;
+ } else {
+ ld->ld_errno = LDAP_SERVER_DOWN;
+ ldap_free_request( ld, lr );
+ ldap_free_connection( ld, lc, 0, 0 );
+ return( -1 );
+ }
+ } else {
+ if ( lr->lr_parent == NULL ) {
+ lr->lr_ber->ber_end = lr->lr_ber->ber_ptr;
+ lr->lr_ber->ber_ptr = lr->lr_ber->ber_buf;
+ }
+ lr->lr_status = LDAP_REQST_INPROGRESS;
+
+ /* sent -- waiting for a response */
+ ldap_mark_select_read( ld, lc->lconn_sb );
+ }
+ return 0;
+}
int
ldap_send_server_request(
}
use_connection( ld, lc );
+
+ /* If we still have an incomplete write, try to finish it before
+ * dealing with the new request. If we don't finish here, return
+ * LDAP_BUSY and let the caller retry later. We only allow a single
+ * request to be in WRITING state.
+ */
+ if ( ld->ld_requests &&
+ ld->ld_requests->lr_status == LDAP_REQST_WRITING &&
+ ldap_int_flush_request( ld, ld->ld_requests ) < 0 ) {
+ return -1;
+ }
+
if (( lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ))) ==
NULL ) {
ld->ld_errno = LDAP_NO_MEMORY;
ld->ld_requests = lr;
lr->lr_prev = NULL;
- if ( ber_flush( lc->lconn_sb, ber, 0 ) != 0 ) {
-#ifdef notyet
- if ( errno == EWOULDBLOCK ) {
- /* need to continue write later */
- lr->lr_status = LDAP_REQST_WRITING;
- ldap_mark_select_write( ld, lc->lconn_sb );
- } else {
-#else /* notyet */
- ld->ld_errno = LDAP_SERVER_DOWN;
- ldap_free_request( ld, lr );
- ldap_free_connection( ld, lc, 0, 0 );
- return( -1 );
-#endif /* notyet */
-#ifdef notyet
- }
-#endif /* notyet */
- } else {
- if ( parentreq == NULL ) {
- ber->ber_end = ber->ber_ptr;
- ber->ber_ptr = ber->ber_buf;
- }
-
- /* sent -- waiting for a response */
- ldap_mark_select_read( ld, lc->lconn_sb );
+ if ( ldap_int_flush_request( ld, lr ) == -1 ) {
+ return -1;
}
ld->ld_errno = LDAP_SUCCESS;
rc = -2; /* select interrupted: loop */
} else {
rc = -2;
+ if ( ld->ld_requests &&
+ ld->ld_requests->lr_status == LDAP_REQST_WRITING &&
+ ldap_is_write_ready( ld,
+ ld->ld_requests->lr_conn->lconn_sb ) ) {
+ ldap_int_flush_request( ld, ld->ld_requests );
+ }
for ( lc = ld->ld_conns; rc == -2 && lc != NULL;
lc = nextlc ) {
nextlc = lc->lconn_next;
# End Source File
# Begin Source File
+SOURCE=.\passfile.c
+# End Source File
+# Begin Source File
+
SOURCE=.\passwd.c
# End Source File
# Begin Source File
Avlnode *ls_vars;
#ifdef USE_REWRITE_LDAP_PVT_THREADS
ldap_pvt_thread_rdwr_t ls_vars_mutex;
+ ldap_pvt_thread_mutex_t ls_mutex;
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
+ int ls_count;
};
/*
assert( s2 != NULL );
assert( s1->ls_cookie != NULL );
assert( s2->ls_cookie != NULL );
-
+
return ( ( s1->ls_cookie < s2->ls_cookie ) ? -1 :
( ( s1->ls_cookie > s2->ls_cookie ) ? 1 : 0 ) );
}
assert( s1->ls_cookie != NULL );
assert( s2->ls_cookie != NULL );
+ assert( s1->ls_cookie != s2->ls_cookie );
+
return ( ( s1->ls_cookie == s2->ls_cookie ) ? -1 : 0 );
}
const void *cookie
)
{
- struct rewrite_session *session;
- int rc;
+ struct rewrite_session *session, tmp;
+ int rc;
assert( info != NULL );
assert( cookie != NULL );
-
+
+#ifdef USE_REWRITE_LDAP_PVT_THREADS
+ ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex );
+#endif /* USE_REWRITE_LDAP_PVT_THREADS */
+
+ tmp.ls_cookie = ( void * )cookie;
+ session = ( struct rewrite_session * )avl_find( info->li_cookies,
+ ( caddr_t )&tmp, rewrite_cookie_cmp );
+ if ( session ) {
+ session->ls_count++;
+#ifdef USE_REWRITE_LDAP_PVT_THREADS
+ ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
+#endif /* USE_REWRITE_LDAP_PVT_THREADS */
+ return session;
+ }
+
session = calloc( sizeof( struct rewrite_session ), 1 );
if ( session == NULL ) {
return NULL;
}
session->ls_cookie = ( void * )cookie;
+ session->ls_count = 1;
#ifdef USE_REWRITE_LDAP_PVT_THREADS
+ if ( ldap_pvt_thread_mutex_init( &session->ls_mutex ) ) {
+ free( session );
+ return NULL;
+ }
if ( ldap_pvt_thread_rdwr_init( &session->ls_vars_mutex ) ) {
+ ldap_pvt_thread_mutex_destroy( &session->ls_mutex );
free( session );
return NULL;
}
- ldap_pvt_thread_rdwr_wlock( &info->li_cookies_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
rc = avl_insert( &info->li_cookies, ( caddr_t )session,
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
if ( rc != 0 ) {
+#ifdef USE_REWRITE_LDAP_PVT_THREADS
+ ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex );
+ ldap_pvt_thread_mutex_destroy( &session->ls_mutex );
+#endif /* USE_REWRITE_LDAP_PVT_THREADS */
+
free( session );
return NULL;
}
session = ( struct rewrite_session * )avl_find( info->li_cookies,
( caddr_t )&tmp, rewrite_cookie_cmp );
#ifdef USE_REWRITE_LDAP_PVT_THREADS
+ if ( session ) {
+ ldap_pvt_thread_mutex_lock( &session->ls_mutex );
+ }
ldap_pvt_thread_rdwr_runlock( &info->li_cookies_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
return session;
-
+}
+
+/*
+ * Returns a session
+ */
+void
+rewrite_session_return(
+ struct rewrite_info *info,
+ struct rewrite_session *session
+)
+{
+ assert( session );
+ ldap_pvt_thread_mutex_unlock( &session->ls_mutex );
}
/*
#ifdef USE_REWRITE_LDAP_PVT_THREADS
ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
+ rewrite_session_return( info, session );
return REWRITE_ERR;
}
}
ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
+ rewrite_session_return( info, session );
+
return REWRITE_SUCCESS;
}
#ifdef USE_REWRITE_LDAP_PVT_THREADS
ldap_pvt_thread_rdwr_runlock( &session->ls_vars_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
-
+
+ rewrite_session_return( info, session );
+
return REWRITE_ERR;
} else {
value->bv_val = strdup( var->lv_value.bv_val );
#ifdef USE_REWRITE_LDAP_PVT_THREADS
ldap_pvt_thread_rdwr_runlock( &session->ls_vars_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
+
+ rewrite_session_return( info, session );
return REWRITE_SUCCESS;
}
session = rewrite_session_find( info, cookie );
if ( session != NULL ) {
+ if ( --session->ls_count > 0 ) {
+ rewrite_session_return( info, session );
+ return REWRITE_SUCCESS;
+ }
+
#ifdef USE_REWRITE_LDAP_PVT_THREADS
ldap_pvt_thread_rdwr_wlock( &session->ls_vars_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
+
rewrite_var_delete( session->ls_vars );
+
#ifdef USE_REWRITE_LDAP_PVT_THREADS
- ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex );
+ ldap_pvt_thread_rdwr_destroy( &session->ls_vars_mutex );
+ ldap_pvt_thread_mutex_destroy( &session->ls_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
}
* There is nothing to delete in the return value
*/
avl_delete( &info->li_cookies, ( caddr_t )&tmp, rewrite_cookie_cmp );
+ free( session );
+
#ifdef USE_REWRITE_LDAP_PVT_THREADS
ldap_pvt_thread_rdwr_wunlock( &info->li_cookies_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
count = avl_free( info->li_cookies, NULL );
info->li_cookies = NULL;
+
+ fprintf( stderr, "count = %d; num_cookies = %d\n",
+ count, info->li_num_cookies );
+
assert( count == info->li_num_cookies );
info->li_num_cookies = 0;
int rc = 1;
Attribute *attr;
- AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass;
const char *group_oc_name = NULL;
const char *group_at_name = group_at->ad_cname.bv_val;
*/
int
-bdb_operational(
+bdb_hasSubordinates(
BackendDB *be,
Connection *conn,
Operation *op,
Entry *e,
- AttributeName *attrs,
- int opattrs,
- Attribute **a )
+ int *hasSubordinates )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
- Attribute **aa = a;
int rc;
DB_TXN *ltid = NULL;
- struct bdb_op_info opinfo;
+ struct bdb_op_info opinfo;
assert( e );
-
- if ( !opattrs && !ad_inlist( slap_schema.si_ad_hasSubordinates, attrs ) ) {
- return 0;
- }
-
+ assert( hasSubordinates );
if( 0 ) {
retry: /* transaction retry */
#endif
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, DETAIL1,
- "=> bdb_operational: retrying...\n", 0, 0, 0 );
+ "=> bdb_hasSubordinates: retrying...\n", 0, 0, 0 );
#else
- Debug( LDAP_DEBUG_TRACE, "==> bdb_operational: retrying...\n",
+ Debug( LDAP_DEBUG_TRACE, "==> bdb_hasSubordinates: retrying...\n",
0, 0, 0 );
#endif
rc = TXN_ABORT( ltid );
if ( rc != 0 ) {
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
- "=> bdb_operational: txn_begin failed: %s (%d)\n",
+ "=> bdb_hasSubordinates: txn_begin failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
#else
Debug( LDAP_DEBUG_TRACE,
- "bdb_operational: txn_begin failed: %s (%d)\n",
+ "bdb_hasSubordinates: txn_begin failed: %s (%d)\n",
db_strerror( rc ), rc, 0 );
#endif
rc = LDAP_OTHER;
goto retry;
case 0:
+ *hasSubordinates = LDAP_COMPARE_TRUE;
+ break;
+
case DB_NOTFOUND:
- *aa = slap_operational_hasSubordinate( rc == 0 );
- if ( *aa != NULL ) {
- aa = &(*aa)->a_next;
- }
+ *hasSubordinates = LDAP_COMPARE_FALSE;
+ rc = LDAP_SUCCESS;
break;
default:
#ifdef NEW_LOGGING
LDAP_LOG ( OPERATION, ERR,
- "=> bdb_operational: has_children failed: %s (%d)\n",
+ "=> bdb_hasSubordinates: has_children failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
#else
Debug(LDAP_DEBUG_ARGS,
- "<=- bdb_operational: has_children failed: %s (%d)\n",
+ "<=- bdb_hasSubordinates: has_children failed: %s (%d)\n",
db_strerror(rc), rc, 0 );
#endif
rc = LDAP_OTHER;
return rc;
}
+int
+bdb_operational(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ AttributeName *attrs,
+ int opattrs,
+ Attribute **a )
+{
+ Attribute **aa = a;
+ int rc = 0;
+
+ assert( e );
+
+ if ( opattrs || ad_inlist( slap_schema.si_ad_hasSubordinates, attrs ) ) {
+ int hasSubordinates;
+
+ rc = bdb_hasSubordinates( be, conn, op, e, &hasSubordinates );
+ if ( rc == LDAP_SUCCESS ) {
+ *aa = slap_operational_hasSubordinate( hasSubordinates == LDAP_COMPARE_TRUE );
+ if ( *aa != NULL ) {
+ aa = &(*aa)->a_next;
+ }
+ }
+ }
+
+ return rc;
+}
+
char *textbuf,
size_t textlen );
+/*
+ * operational.c
+ */
+int
+bdb_hasSubordinates(
+ BackendDB *be,
+ Connection *conn,
+ Operation *op,
+ Entry *e,
+ int *hasSubordinates );
+
/*
* passwd.c
*/
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;
if (e) {
int result;
+#if 0 /* noop is masked SLAP_CTRL_UPDATE */
if( op->o_noop ) {
result = 0;
} else {
+#endif
result = send_search_entry( be, conn, op,
e, attrs, attrsonly, NULL);
+#if 0
}
+#endif
switch (result) {
case 0: /* entry sent ok */
}
} 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) {
if ( be->bd_info->bi_open ) {
rc = be->bd_info->bi_open( be->bd_info );
- }
-
- if(rc != 0) {
+ if ( rc != 0 ) {
#ifdef NEW_LOGGING
- LDAP_LOG( BACKEND, CRIT, "backend_startup: bi_open failed!\n", 0, 0, 0 );
+ LDAP_LOG( BACKEND, CRIT, "backend_startup: bi_open failed!\n", 0, 0, 0 );
#else
- Debug( LDAP_DEBUG_ANY,
- "backend_startup: bi_open failed!\n",
- 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY,
+ "backend_startup: bi_open failed!\n",
+ 0, 0, 0 );
#endif
- return rc;
+ return rc;
+ }
}
if ( be->bd_info->bi_db_open ) {
rc = be->bd_info->bi_db_open( be );
- }
-
- if(rc != 0) {
+ if ( rc != 0 ) {
#ifdef NEW_LOGGING
- LDAP_LOG( BACKEND, CRIT,
- "backend_startup: bi_db_open failed! (%d)\n", rc, 0, 0 );
+ LDAP_LOG( BACKEND, CRIT,
+ "backend_startup: bi_db_open failed! (%d)\n", rc, 0, 0 );
#else
- Debug( LDAP_DEBUG_ANY,
- "backend_startup: bi_db_open failed! (%d)\n",
- rc, 0, 0 );
+ Debug( LDAP_DEBUG_ANY,
+ "backend_startup: bi_db_open failed! (%d)\n",
+ rc, 0, 0 );
#endif
- return rc;
+ return rc;
+ }
}
return rc;
if( backendInfo[i].bi_open ) {
rc = backendInfo[i].bi_open(
&backendInfo[i] );
- }
-
- if(rc != 0) {
+ if ( rc != 0 ) {
#ifdef NEW_LOGGING
- LDAP_LOG( BACKEND, CRIT,
- "backend_startup: bi_open %d failed!\n", i, 0, 0 );
+ LDAP_LOG( BACKEND, CRIT,
+ "backend_startup: bi_open %d failed!\n", i, 0, 0 );
#else
- Debug( LDAP_DEBUG_ANY,
- "backend_startup: bi_open %d failed!\n",
- i, 0, 0 );
+ Debug( LDAP_DEBUG_ANY,
+ "backend_startup: bi_open %d failed!\n",
+ i, 0, 0 );
#endif
- return rc;
+ return rc;
+ }
}
}
if ( backendDB[i].bd_info->bi_db_open ) {
rc = backendDB[i].bd_info->bi_db_open(
&backendDB[i] );
- }
-
- if(rc != 0) {
+ if ( rc != 0 ) {
#ifdef NEW_LOGGING
- LDAP_LOG( BACKEND, CRIT,
- "backend_startup: bi_db_open(%d) failed! (%d)\n", i, rc, 0 );
+ LDAP_LOG( BACKEND, CRIT,
+ "backend_startup: bi_db_open(%d) failed! (%d)\n", i, rc, 0 );
#else
- Debug( LDAP_DEBUG_ANY,
- "backend_startup: bi_db_open(%d) failed! (%d)\n",
- i, rc, 0 );
+ Debug( LDAP_DEBUG_ANY,
+ "backend_startup: bi_db_open(%d) failed! (%d)\n",
+ i, rc, 0 );
#endif
- return rc;
+ return rc;
+ }
}
}
return LDAP_SUCCESS;
}
+ if ( be->be_controls == NULL ) {
+ *text = "control unavailable in context";
+ return LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
+ }
+
for( ; *ctrls != NULL ; ctrls++ ) {
if( (*ctrls)->ldctl_iscritical &&
!ldap_charray_inlist( be->be_controls, (*ctrls)->ldctl_oid ) )
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;
}
static const char* slap_name = NULL;
int slapMode = SLAP_UNDEFINED_MODE;
+/*
+ * all known control OIDs should be added to this list
+ */
+char *slap_known_controls[] = {
+#ifdef LDAP_CONTROL_REFERRALS
+ LDAP_CONTROL_REFERRALS,
+#endif /* LDAP_CONTROL_REFERRALS */
+
+#ifdef LDAP_CONTROL_MANAGEDSAIT
+ LDAP_CONTROL_MANAGEDSAIT,
+#endif /* LDAP_CONTROL_MANAGEDSAIT */
+
+#ifdef LDAP_CONTROL_SUBENTRIES
+ LDAP_CONTROL_SUBENTRIES,
+#endif /* LDAP_CONTROL_SUBENTRIES */
+
+#ifdef LDAP_CONTROL_NOOP
+ LDAP_CONTROL_NOOP,
+#endif /* LDAP_CONTROL_NOOP */
+
+#ifdef LDAP_CONTROL_DUPENT_REQUEST
+ LDAP_CONTROL_DUPENT_REQUEST,
+#endif /* LDAP_CONTROL_DUPENT_REQUEST */
+
+#ifdef LDAP_CONTROL_DUPENT_RESPONSE
+ LDAP_CONTROL_DUPENT_RESPONSE,
+#endif /* LDAP_CONTROL_DUPENT_RESPONSE */
+
+#ifdef LDAP_CONTROL_DUPENT_ENTRY
+ LDAP_CONTROL_DUPENT_ENTRY,
+#endif /* LDAP_CONTROL_DUPENT_ENTRY */
+
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+ LDAP_CONTROL_PAGEDRESULTS,
+#endif /* LDAP_CONTROL_PAGEDRESULTS */
+
+#ifdef LDAP_CONTROL_SORTREQUEST
+ LDAP_CONTROL_SORTREQUEST,
+#endif /* LDAP_CONTROL_SORTREQUEST */
+
+#ifdef LDAP_CONTROL_SORTRESPONSE
+ LDAP_CONTROL_SORTRESPONSE,
+#endif /* LDAP_CONTROL_SORTRESPONSE */
+
+#ifdef LDAP_CONTROL_VLVREQUEST
+ LDAP_CONTROL_VLVREQUEST,
+#endif /* LDAP_CONTROL_VLVREQUEST */
+
+#ifdef LDAP_CONTROL_VLVRESPONSE
+ LDAP_CONTROL_VLVRESPONSE,
+#endif /* LDAP_CONTROL_VLVRESPONSE */
+
+#ifdef LDAP_CONTROL_VALUESRETURNFILTER
+ LDAP_CONTROL_VALUESRETURNFILTER,
+#endif /* LDAP_CONTROL_VALUESRETURNFILTER */
+
+ NULL
+};
+
int
slap_init( int mode, const char *name )
{
#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 rc;
}
- if ( ret ) {
+ if ( ret == 0 ) {
(*e_flags)[i][j] = 1;
}
}
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 );
slap_operational_hasSubordinate( int hs )
{
Attribute *a;
-
+ char *val;
+ ber_len_t len;
+
+ if ( hs ) {
+ val = "TRUE";
+ len = sizeof( "TRUE" ) - 1;
+
+ } else {
+ val = "FALSE";
+ len = sizeof( "FALSE" ) - 1;
+
+ }
+
a = ch_malloc( sizeof( Attribute ) );
a->a_desc = slap_schema.si_ad_hasSubordinates;
-
a->a_vals = ch_malloc( 2 * sizeof( struct berval ) );
- ber_str2bv( hs ? "TRUE" : "FALSE",
- hs ? sizeof("TRUE")-1 : sizeof("FALSE")-1,
- 1, a->a_vals );
+
+ ber_str2bv( val, len, 1, a->a_vals );
a->a_vals[1].bv_val = NULL;
a->a_next = NULL;
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 LDAP_P(( ValuesReturnFilter *f ));
+LDAP_SLAPD_F (void) vrFilter2bv LDAP_P(( ValuesReturnFilter *f, struct berval *fstr ));
-LDAP_SLAPD_F (void) vrFilter_free( ValuesReturnFilter *f );
-LDAP_SLAPD_F (void) vrFilter2bv( 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 ));
LDAP_SLAPD_F (int) slap_shutdown LDAP_P(( Backend *be ));
LDAP_SLAPD_F (int) slap_destroy LDAP_P((void));
+LDAP_SLAPD_V (char *) slap_known_controls[];
+
/*
* kerberos.c
*/
* to ValuesReturnFilter or 0 if not
*/
if ( op->vrFilter != NULL ) {
- int k = 0;
- char *a_flags;
+ int k = 0;
+ size_t size;
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++ ) k++;
}
- e_flags = ch_calloc ( 1, i * sizeof(char *) + k );
- a_flags = (char *)(e_flags + i);
- 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;
- a_flags += j;
- }
- rc = filter_matched_values(be, conn, op, e->e_attrs, &e_flags) ;
- if ( rc == -1 ) {
+ size = i * sizeof(char *) + k;
+ if ( size > 0 ) {
+ char *a_flags;
+ 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;
+ a_flags += j;
+ }
+
+ rc = filter_matched_values(be, conn, op, e->e_attrs, &e_flags) ;
+ if ( rc == -1 ) {
#ifdef NEW_LOGGING
- LDAP_LOG( OPERATION, ERR,
- "send_search_entry: conn %lu matched values filtering failed\n",
- conn ? conn->c_connid : 0, 0, 0 );
+ LDAP_LOG( OPERATION, ERR,
+ "send_search_entry: conn %lu matched values filtering failed\n",
+ conn ? conn->c_connid : 0, 0, 0 );
#else
- Debug( LDAP_DEBUG_ANY,
- "matched values filtering failed\n", 0, 0, 0 );
+ Debug( LDAP_DEBUG_ANY,
+ "matched values filtering failed\n", 0, 0, 0 );
#endif
- ber_free( ber, 1 );
-
- send_ldap_result( conn, op, LDAP_OTHER,
- NULL, "matched values filtering error",
- NULL, NULL );
- goto error_return;
+ ber_free( ber, 1 );
+
+ send_ldap_result( conn, op, LDAP_OTHER,
+ NULL, "matched values filtering error",
+ NULL, NULL );
+ goto error_return;
+ }
}
}
}
}
- /* 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;
+ int k = 0;
+ size_t size;
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 );
- a_flags = (char *)(e_flags + i);
- 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;
- a_flags += j;
- }
- rc = filter_matched_values(be, conn, op, aa, &e_flags) ;
-
- if ( rc == -1 ) {
+
+ size = i * sizeof(char *) + k;
+ if ( size > 0 ) {
+ char *a_flags, **tmp;
+
+ /*
+ * 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 "
- "matched values filtering failed\n",
- conn ? conn->c_connid : 0, 0, 0);
+ 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,
- "matched values filtering failed\n", 0, 0, 0 );
+ 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_OTHER,
- NULL, "matched values filtering error",
- NULL, NULL );
- goto error_return;
+ 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;
+ a_flags += j;
+ }
+ rc = filter_matched_values(be, conn, op, aa, &e_flags) ;
+
+ if ( rc == -1 ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG( OPERATION, ERR,
+ "send_search_entry: conn %lu "
+ "matched values filtering failed\n",
+ conn ? conn->c_connid : 0, 0, 0);
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "matched values filtering failed\n", 0, 0, 0 );
+#endif
+ ber_free( ber, 1 );
+
+ send_ldap_result( conn, op, LDAP_OTHER,
+ NULL, "matched values filtering error",
+ NULL, NULL );
+ goto error_return;
+ }
}
}
= slap_schema.si_ad_objectClass;
Entry *e;
- struct berval vals[2];
-
- vals[1].bv_val = NULL;
+ struct berval vals[5];
e = (Entry *) ch_calloc( 1, sizeof(Entry) );
vals[0].bv_val = "subentry";
vals[0].bv_len = sizeof("subentry")-1;
- attr_merge( e, ad_structuralObjectClass, vals );
+ attr_merge_one( e, ad_structuralObjectClass, vals );
vals[0].bv_val = "top";
vals[0].bv_len = sizeof("top")-1;
- attr_merge( e, ad_objectClass, vals );
-
- vals[0].bv_val = "subentry";
- vals[0].bv_len = sizeof("subentry")-1;
- attr_merge( e, ad_objectClass, vals );
-
- vals[0].bv_val = "subschema";
- vals[0].bv_len = sizeof("subschema")-1;
- attr_merge( e, ad_objectClass, vals );
-
- vals[0].bv_val = "extensibleObject";
- vals[0].bv_len = sizeof("extensibleObject")-1;
+ vals[1].bv_val = "subentry";
+ vals[1].bv_len = sizeof("subentry")-1;
+ vals[2].bv_val = "subschema";
+ vals[2].bv_len = sizeof("subschema")-1;
+ vals[3].bv_val = "extensibleObject";
+ vals[3].bv_len = sizeof("extensibleObject")-1;
+ vals[4].bv_val = NULL;
attr_merge( e, ad_objectClass, vals );
{
return LDAP_OTHER;
}
- attr_merge( e, desc, vals );
+ attr_merge_one( e, desc, vals );
}
if ( syn_schema_info( e )
send_ldap_disconnect( conn, op,
LDAP_PROTOCOL_ERROR, text );
} else {
- send_ldap_result( conn, op, rc,
- NULL, text, NULL, NULL );
+ send_ldap_result( conn, op, rc,
+ NULL, text, NULL, NULL );
}
goto return_results;
-
- } else {
- filter2bv( filter, &fstr );
}
+ filter2bv( filter, &fstr );
#ifdef NEW_LOGGING
LDAP_LOG( OPERATION, ARGS,
if ( be->be_search ) {
(*be->be_search)( be, conn, op, &pbase, &nbase,
scope, deref, sizelimit,
- timelimit, filter, &fstr, an, attrsonly );
+ timelimit, filter, &fstr, an, attrsonly );
} else {
send_ldap_result( conn, op, rc = LDAP_UNWILLING_TO_PERFORM,
NULL, "operation not supported within namingContext",
};
#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"