From 71457e7b02dda4086677cbd1c49dd580935cbb96 Mon Sep 17 00:00:00 2001 From: Kurt Zeilenga Date: Fri, 30 Aug 2002 03:06:17 +0000 Subject: [PATCH] Sync with HEAD --- build/main.dsw | 48 ++++---- doc/devel/todo | 6 +- libraries/liblber/sockbuf.c | 5 - libraries/libldap/abandon.c | 2 +- libraries/libldap/cyrus.c | 32 ++++- libraries/libldap/filter.c | 11 +- libraries/libldap/ldap-int.h | 1 + libraries/libldap/request.c | 71 +++++++---- libraries/libldap/result.c | 6 + libraries/liblutil/liblutil.dsp | 4 + libraries/librewrite/rewrite-int.h | 2 + libraries/librewrite/session.c | 79 ++++++++++-- servers/slapd/back-bdb/group.c | 1 - servers/slapd/back-bdb/operational.c | 66 ++++++---- servers/slapd/back-bdb/proto-bdb.h | 11 ++ servers/slapd/back-bdb/search.c | 63 +++++++++- servers/slapd/back-ldbm/search.c | 56 ++++++++- servers/slapd/backend.c | 71 +++++------ servers/slapd/dn.c | 58 ++++++++- servers/slapd/filter.c | 143 +++++++++++++++++++++- servers/slapd/filterentry.c | 172 ++++++++++++++++++++++++--- servers/slapd/init.c | 59 +++++++++ servers/slapd/matchedValues.c | 43 ++++++- servers/slapd/mra.c | 87 +++++++++++--- servers/slapd/operational.c | 20 +++- servers/slapd/proto-slap.h | 31 ++++- servers/slapd/result.c | 136 +++++++++++++-------- servers/slapd/schema.c | 27 ++--- servers/slapd/search.c | 10 +- servers/slapd/slap.h | 6 + 30 files changed, 1065 insertions(+), 262 deletions(-) diff --git a/build/main.dsw b/build/main.dsw index f198bf3c05..b5d01bfcb8 100644 --- a/build/main.dsw +++ b/build/main.dsw @@ -123,9 +123,6 @@ Package=<4> 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 @@ -155,6 +152,9 @@ Package=<4> Begin Project Dependency Project_Dep_Name ftest End Project Dependency + Begin Project Dependency + Project_Dep_Name ldapwhoami + End Project Dependency }}} ############################################################################### @@ -354,6 +354,27 @@ Package=<4> ############################################################################### +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> @@ -777,27 +798,6 @@ Package=<4> ############################################################################### -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> diff --git a/doc/devel/todo b/doc/devel/todo index 5a4d74df65..a2cd3978dd 100644 --- a/doc/devel/todo +++ b/doc/devel/todo @@ -31,7 +31,7 @@ OpenLDAP 2.x Projects 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 @@ -41,16 +41,14 @@ Implement LDAP Transactions extension 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 macros Create ldapbind(1) to support bind operations diff --git a/libraries/liblber/sockbuf.c b/libraries/liblber/sockbuf.c index ae5c07c8c1..7fa6e85321 100644 --- a/libraries/liblber/sockbuf.c +++ b/libraries/liblber/sockbuf.c @@ -313,11 +313,6 @@ ber_pvt_sb_do_write( Sockbuf_IO_Desc *sbiod, Sockbuf_Buf *buf_out ) 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; } diff --git a/libraries/libldap/abandon.c b/libraries/libldap/abandon.c index a88a5865b5..04397a275e 100644 --- a/libraries/libldap/abandon.c +++ b/libraries/libldap/abandon.c @@ -224,7 +224,7 @@ do_abandon( } 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 ) { diff --git a/libraries/libldap/cyrus.c b/libraries/libldap/cyrus.c index 1e6e9f42cf..85b248de67 100644 --- a/libraries/libldap/cyrus.c +++ b/libraries/libldap/cyrus.c @@ -331,8 +331,13 @@ sb_sasl_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) /* 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. */ @@ -1088,6 +1093,7 @@ ldap_int_sasl_set_option( LDAP *ld, int option, void *arg ) } #ifdef LDAP_R_COMPILE +#define LDAP_DEBUG_R_SASL void *ldap_pvt_sasl_mutex_new(void) { ldap_pvt_thread_mutex_t *mutex; @@ -1098,23 +1104,47 @@ void *ldap_pvt_sasl_mutex_new(void) 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 ); } diff --git a/libraries/libldap/filter.c b/libraries/libldap/filter.c index 259c9a4590..2ff345dd6d 100644 --- a/libraries/libldap/filter.c +++ b/libraries/libldap/filter.c @@ -837,8 +837,7 @@ put_vrFilter( BerElement *ber, const char *str_in ) */ #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 @@ -933,9 +932,9 @@ put_vrFilter( BerElement *ber, const char *str_in ) 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 ) { @@ -952,10 +951,10 @@ put_vrFilter( BerElement *ber, const char *str_in ) 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' ); diff --git a/libraries/libldap/ldap-int.h b/libraries/libldap/ldap-int.h index 4ad20dd9f4..5e44c3287d 100644 --- a/libraries/libldap/ldap-int.h +++ b/libraries/libldap/ldap-int.h @@ -467,6 +467,7 @@ LDAP_F (int) ldap_chase_referrals( LDAP *ld, LDAPRequest *lr, 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: diff --git a/libraries/libldap/request.c b/libraries/libldap/request.c index b9ecd9b3bd..0ffd592b21 100644 --- a/libraries/libldap/request.c +++ b/libraries/libldap/request.c @@ -137,6 +137,39 @@ ldap_send_initial_request( } +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( @@ -189,6 +222,18 @@ 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; @@ -225,30 +270,8 @@ ldap_send_server_request( 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; diff --git a/libraries/libldap/result.c b/libraries/libldap/result.c index 1a7bcec9ef..2f82aa9422 100644 --- a/libraries/libldap/result.c +++ b/libraries/libldap/result.c @@ -334,6 +334,12 @@ wait4msg( 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; diff --git a/libraries/liblutil/liblutil.dsp b/libraries/liblutil/liblutil.dsp index 436a6981bf..013a800c12 100644 --- a/libraries/liblutil/liblutil.dsp +++ b/libraries/liblutil/liblutil.dsp @@ -204,6 +204,10 @@ SOURCE=.\ntservice.c # End Source File # Begin Source File +SOURCE=.\passfile.c +# End Source File +# Begin Source File + SOURCE=.\passwd.c # End Source File # Begin Source File diff --git a/libraries/librewrite/rewrite-int.h b/libraries/librewrite/rewrite-int.h index 28e47e46c6..b8bc161a54 100644 --- a/libraries/librewrite/rewrite-int.h +++ b/libraries/librewrite/rewrite-int.h @@ -243,7 +243,9 @@ struct rewrite_session { 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; }; /* diff --git a/libraries/librewrite/session.c b/libraries/librewrite/session.c index fa5c78354a..1e93ecd777 100644 --- a/libraries/librewrite/session.c +++ b/libraries/librewrite/session.c @@ -44,7 +44,7 @@ rewrite_cookie_cmp( 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 ) ); } @@ -68,6 +68,8 @@ rewrite_cookie_dup( 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 ); } @@ -80,24 +82,44 @@ rewrite_session_init( 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, @@ -109,6 +131,11 @@ rewrite_session_init( #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; } @@ -137,11 +164,26 @@ rewrite_session_find( 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 ); } /* @@ -184,6 +226,7 @@ rewrite_session_var_set( #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; } } @@ -192,6 +235,8 @@ rewrite_session_var_set( ldap_pvt_thread_rdwr_wunlock( &session->ls_vars_mutex ); #endif /* USE_REWRITE_LDAP_PVT_THREADS */ + rewrite_session_return( info, session ); + return REWRITE_SUCCESS; } @@ -236,7 +281,9 @@ rewrite_session_var_get( #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 ); @@ -246,6 +293,8 @@ rewrite_session_var_get( #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; } @@ -269,12 +318,20 @@ rewrite_session_delete( 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 */ } @@ -289,6 +346,8 @@ rewrite_session_delete( * 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 */ @@ -318,6 +377,10 @@ rewrite_session_destroy( 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; diff --git a/servers/slapd/back-bdb/group.c b/servers/slapd/back-bdb/group.c index d4fb4de09e..f774bb1831 100644 --- a/servers/slapd/back-bdb/group.c +++ b/servers/slapd/back-bdb/group.c @@ -40,7 +40,6 @@ bdb_group( 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; diff --git a/servers/slapd/back-bdb/operational.c b/servers/slapd/back-bdb/operational.c index cfcf17cdb3..1c5d4b14d6 100644 --- a/servers/slapd/back-bdb/operational.c +++ b/servers/slapd/back-bdb/operational.c @@ -20,27 +20,20 @@ */ 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 */ @@ -51,9 +44,9 @@ 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 ); @@ -71,11 +64,11 @@ retry: /* transaction retry */ 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; @@ -95,21 +88,22 @@ retry: /* transaction retry */ 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; @@ -130,3 +124,33 @@ return_results: 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; +} + diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index 8fa8b55181..6c7dfeb586 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -300,6 +300,17 @@ int bdb_modify_internal( char *textbuf, size_t textlen ); +/* + * operational.c + */ +int +bdb_hasSubordinates( + BackendDB *be, + Connection *conn, + Operation *op, + Entry *e, + int *hasSubordinates ); + /* * passwd.c */ diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c index 462d8ec027..30abec8b25 100644 --- a/servers/slapd/back-bdb/search.c +++ b/servers/slapd/back-bdb/search.c @@ -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; @@ -525,12 +579,16 @@ id2entry_retry: 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 */ @@ -557,8 +615,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 +832,4 @@ static int search_candidates( return rc; } + diff --git a/servers/slapd/back-ldbm/search.c b/servers/slapd/back-ldbm/search.c index 87f4b9278b..eac5f831e9 100644 --- a/servers/slapd/back-ldbm/search.c +++ b/servers/slapd/back-ldbm/search.c @@ -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) { diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index 461fc7a9f5..b5f3fe0440 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -254,34 +254,32 @@ int backend_startup(Backend *be) 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; @@ -297,18 +295,17 @@ int backend_startup(Backend *be) 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; + } } } @@ -320,18 +317,17 @@ int backend_startup(Backend *be) 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; + } } } @@ -746,6 +742,11 @@ backend_check_controls( 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 ) ) diff --git a/servers/slapd/dn.c b/servers/slapd/dn.c index 9194a9cb53..0084a7c80a 100644 --- a/servers/slapd/dn.c +++ b/servers/slapd/dn.c @@ -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 */ diff --git a/servers/slapd/filter.c b/servers/slapd/filter.c index 69a26bf34b..608b732c84 100644 --- a/servers/slapd/filter.c +++ b/servers/slapd/filter.c @@ -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 */ + diff --git a/servers/slapd/filterentry.c b/servers/slapd/filterentry.c index 672915cb8c..111e258e61 100644 --- a/servers/slapd/filterentry.c +++ b/servers/slapd/filterentry.c @@ -215,36 +215,174 @@ 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; + + 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; } diff --git a/servers/slapd/init.c b/servers/slapd/init.c index d091c4fe07..90f66152ea 100644 --- a/servers/slapd/init.c +++ b/servers/slapd/init.c @@ -71,6 +71,65 @@ ldap_pvt_thread_mutex_t replog_mutex; 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 ) { diff --git a/servers/slapd/matchedValues.c b/servers/slapd/matchedValues.c index 483a14956d..51c223e97d 100644 --- a/servers/slapd/matchedValues.c +++ b/servers/slapd/matchedValues.c @@ -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,14 +398,14 @@ 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 ) { return rc; } - if ( ret ) { + if ( ret == 0 ) { (*e_flags)[i][j] = 1; } } diff --git a/servers/slapd/mra.c b/servers/slapd/mra.c index eca939b026..d4e331f194 100644 --- a/servers/slapd/mra.c +++ b/servers/slapd/mra.c @@ -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 - /* 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 ); diff --git a/servers/slapd/operational.c b/servers/slapd/operational.c index b9396b2473..f6b45221f8 100644 --- a/servers/slapd/operational.c +++ b/servers/slapd/operational.c @@ -40,14 +40,24 @@ Attribute * 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; diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 95720738d0..f51f24a18b 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -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 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 )); @@ -479,6 +500,8 @@ LDAP_SLAPD_F (int) slap_startup LDAP_P(( Backend *be )); 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 */ diff --git a/servers/slapd/result.c b/servers/slapd/result.c index ccc1de3083..ed5f85f782 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -762,36 +762,42 @@ send_search_entry( * 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; + } } } @@ -909,48 +915,74 @@ 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; + 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; + } } } diff --git a/servers/slapd/schema.c b/servers/slapd/schema.c index 725995150f..874ace374c 100644 --- a/servers/slapd/schema.c +++ b/servers/slapd/schema.c @@ -28,9 +28,7 @@ schema_info( Entry **entry, const char **text ) = 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) ); @@ -44,22 +42,17 @@ schema_info( Entry **entry, const char **text ) 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 ); { @@ -85,7 +78,7 @@ schema_info( Entry **entry, const char **text ) return LDAP_OTHER; } - attr_merge( e, desc, vals ); + attr_merge_one( e, desc, vals ); } if ( syn_schema_info( e ) diff --git a/servers/slapd/search.c b/servers/slapd/search.c index 90cb1927cc..fada8cb8cd 100644 --- a/servers/slapd/search.c +++ b/servers/slapd/search.c @@ -142,14 +142,12 @@ do_search( 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, @@ -319,7 +317,7 @@ do_search( 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", diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 86a324d736..e64d7e87b9 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -1675,6 +1675,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" -- 2.39.5