From ea83f6a66972de84aa3efe2cd53f50f69465588c Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Fri, 25 Nov 2005 00:28:33 +0000 Subject: [PATCH] check sizelimit in frontend (ITS#4213) --- servers/slapd/back-bdb/search.c | 31 +++++++++----------- servers/slapd/back-ldap/search.c | 3 ++ servers/slapd/back-ldbm/search.c | 19 +++++------- servers/slapd/back-meta/search.c | 45 +++++++++++++++++++---------- servers/slapd/back-monitor/search.c | 2 +- servers/slapd/back-perl/search.c | 13 +++++++-- servers/slapd/back-sql/search.c | 12 ++++---- servers/slapd/overlays/retcode.c | 4 +++ servers/slapd/result.c | 18 ++++++++++++ servers/slapd/slap.h | 7 +++-- 10 files changed, 98 insertions(+), 56 deletions(-) diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c index 3151d3d6aa..9b7a94f2f2 100644 --- a/servers/slapd/back-bdb/search.c +++ b/servers/slapd/back-bdb/search.c @@ -858,21 +858,6 @@ fetch_entry_retry: if ( rs->sr_err == LDAP_COMPARE_TRUE ) { /* check size limit */ - if ( --op->ors_slimit == -1 ) { -#ifdef SLAP_ZONE_ALLOC - slap_zn_runlock(bdb->bi_cache.c_zctx, e); -#endif - bdb_cache_return_entry_r( bdb->bi_dbenv, - &bdb->bi_cache, e, &lock ); - e = NULL; - rs->sr_entry = NULL; - rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; - rs->sr_ref = rs->sr_v2ref; - send_ldap_result( op, rs ); - rs->sr_err = LDAP_SUCCESS; - goto done; - } - if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) { if ( rs->sr_nentries >= ((PagedResultsState *)op->o_pagedresults_state)->ps_size ) { #ifdef SLAP_ZONE_ALLOC @@ -897,12 +882,12 @@ fetch_entry_retry: rs->sr_err = LDAP_SUCCESS; result = send_search_entry( op, rs ); - switch (result) { + switch ( result ) { case 0: /* entry sent ok */ break; case 1: /* entry not sent */ break; - case -1: /* connection closed */ + default: #ifdef SLAP_ZONE_ALLOC slap_zn_runlock(bdb->bi_cache.c_zctx, e); #endif @@ -910,7 +895,17 @@ fetch_entry_retry: &bdb->bi_cache, e, &lock); e = NULL; rs->sr_entry = NULL; - rs->sr_err = LDAP_OTHER; + switch ( result ) { + case SLAPD_SEND_SIZELIMIT: + rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; + rs->sr_ref = rs->sr_v2ref; + send_ldap_result( op, rs ); + rs->sr_err = LDAP_SUCCESS; + break; + case -1: /* connection closed */ + rs->sr_err = LDAP_OTHER; + break; + } goto done; } } diff --git a/servers/slapd/back-ldap/search.c b/servers/slapd/back-ldap/search.c index e1a8880086..eb70948b44 100644 --- a/servers/slapd/back-ldap/search.c +++ b/servers/slapd/back-ldap/search.c @@ -311,6 +311,9 @@ retry: } ldap_msgfree( res ); if ( abort ) { + if ( abort == SLAPD_SEND_SIZELIMIT ) { + rc = rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; + } ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL ); goto finish; } diff --git a/servers/slapd/back-ldbm/search.c b/servers/slapd/back-ldbm/search.c index 47e7886ee1..75aa5347f7 100644 --- a/servers/slapd/back-ldbm/search.c +++ b/servers/slapd/back-ldbm/search.c @@ -430,21 +430,11 @@ searchit: } if ( scopeok ) { - /* check size limit */ - if ( --op->ors_slimit == -1 ) { - cache_return_entry_r( &li->li_cache, e ); - rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; - rs->sr_entry = NULL; - send_ldap_result( op, rs ); - rc = LDAP_SUCCESS; - goto done; - } - if (e) { rs->sr_flags = 0; result = send_search_entry( op, rs ); - switch (result) { + switch ( result ) { case 0: /* entry sent ok */ break; case 1: /* entry not sent */ @@ -453,6 +443,13 @@ searchit: cache_return_entry_r( &li->li_cache, e ); rc = LDAP_SUCCESS; goto done; + case SLAPD_SEND_SIZELIMIT: + cache_return_entry_r( &li->li_cache, e ); + rc = rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; + rs->sr_entry = NULL; + send_ldap_result( op, rs ); + rc = LDAP_SUCCESS; + goto done; } } diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index 2f9fb36497..ae6e5c2616 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -451,29 +451,30 @@ really_bad:; candidates[ i ].sr_type = REP_RESULT; } - if ( --op->ors_slimit == -1 ) { - ldap_msgfree( res ); - res = NULL; + is_ok++; + + e = ldap_first_entry( msc->msc_ld, res ); + savepriv = op->o_private; + op->o_private = (void *)i; + rc = meta_send_entry( op, rs, mc, i, e ); + ldap_msgfree( res ); + res = NULL; + switch ( rc ) { + case SLAPD_SEND_SIZELIMIT: rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; savepriv = op->o_private; op->o_private = (void *)i; send_ldap_result( op, rs ); op->o_private = savepriv; goto finish; - } - is_ok++; - - e = ldap_first_entry( msc->msc_ld, res ); - savepriv = op->o_private; - op->o_private = (void *)i; - meta_send_entry( op, rs, mc, i, e ); + case -1: + rs->sr_err = LDAP_OTHER; + goto finish; + } op->o_private = savepriv; - ldap_msgfree( res ); - res = NULL; - gotit = 1; #if 0 @@ -1155,7 +1156,21 @@ next_attr:; rs->sr_entry = &ent; rs->sr_attrs = op->ors_attrs; rs->sr_flags = 0; - send_search_entry( op, rs ); + switch ( send_search_entry( op, rs ) ) { + case 0: + case 1: + rc = LDAP_SUCCESS; + break; + case -1: + rc = LDAP_OTHER; + break; + case SLAPD_SEND_SIZELIMIT: + rc = LDAP_SIZELIMIT_EXCEEDED; + break; + default: + /* trap other values when added... */ + assert( 0 ); + } rs->sr_entry = NULL; rs->sr_attrs = NULL; @@ -1169,6 +1184,6 @@ next_attr:; } entry_clean( &ent ); - return LDAP_SUCCESS; + return rc; } diff --git a/servers/slapd/back-monitor/search.c b/servers/slapd/back-monitor/search.c index 591287d06c..ab5c475c07 100644 --- a/servers/slapd/back-monitor/search.c +++ b/servers/slapd/back-monitor/search.c @@ -113,7 +113,7 @@ monitor_send_children( if ( rc == LDAP_COMPARE_TRUE ) { rs->sr_entry = e; rs->sr_flags = 0; - send_search_entry( op, rs ); + rc = send_search_entry( op, rs ); rs->sr_entry = NULL; } diff --git a/servers/slapd/back-perl/search.c b/servers/slapd/back-perl/search.c index 33d4822553..565402172c 100644 --- a/servers/slapd/back-perl/search.c +++ b/servers/slapd/back-perl/search.c @@ -84,10 +84,18 @@ perl_back_search( send_entry = 1; if (send_entry) { + int rc; + rs->sr_entry = e; rs->sr_attrs = op->ors_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; - send_search_entry( op, rs ); + rc = send_search_entry( op, rs ); + switch ( rc ) { + case SLAPD_SEND_SIZELIMIT: + rs->sr_entry = NULL; + rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; + goto done2; + } } entry_free( e ); @@ -106,8 +114,7 @@ perl_back_search( rs->sr_err = POPi; - - +done:; PUTBACK; FREETMPS; LEAVE; } diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c index 1f49f18b3b..7c001fbb2f 100644 --- a/servers/slapd/back-sql/search.c +++ b/servers/slapd/back-sql/search.c @@ -2320,11 +2320,6 @@ backsql_search( Operation *op, SlapReply *rs ) if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { - if ( --op->ors_slimit == -1 ) { - rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; - goto send_results; - } - rs->sr_attrs = op->ors_attrs; rs->sr_operational_attrs = NULL; rs->sr_entry = e; @@ -2335,7 +2330,8 @@ backsql_search( Operation *op, SlapReply *rs ) rs->sr_attrs = NULL; rs->sr_operational_attrs = NULL; - if ( sres == -1 ) { + switch ( sres ) { + case -1: /* * FIXME: send_search_entry failed; * better stop @@ -2343,6 +2339,10 @@ backsql_search( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_TRACE, "backsql_search(): " "connection lost\n", 0, 0, 0 ); goto end_of_search; + + case SLAPD_SEND_SIZELIMIT: + rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; + goto send_results; } } diff --git a/servers/slapd/overlays/retcode.c b/servers/slapd/overlays/retcode.c index 845370a812..773ef0a37b 100644 --- a/servers/slapd/overlays/retcode.c +++ b/servers/slapd/overlays/retcode.c @@ -146,6 +146,10 @@ retcode_send_onelevel( Operation *op, SlapReply *rs ) rs->sr_entry = NULL; rs->sr_err = LDAP_OTHER; goto done; + case SLAPD_SEND_SIZELIMIT: + rs->sr_entry = NULL; + rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; + goto done; } } rs->sr_err = LDAP_SUCCESS; diff --git a/servers/slapd/result.c b/servers/slapd/result.c index cb9e25ad70..5b085af138 100644 --- a/servers/slapd/result.c +++ b/servers/slapd/result.c @@ -662,6 +662,15 @@ slap_send_ldap_intermediate( Operation *op, SlapReply *rs ) } } +/* + * returns: + * + * 0 entry sent + * 1 entry not sent (other) + * -1 entry not sent (connection closed) + * SLAPD_SEND_SIZELIMIT entry not sent (caller must send sizelimitExceeded) + */ + int slap_send_search_entry( Operation *op, SlapReply *rs ) { @@ -1116,6 +1125,15 @@ slap_send_search_entry( Operation *op, SlapReply *rs ) } if ( op->o_res_ber == NULL ) { + if ( --op->ors_slimit == -1 ) { + rc = SLAPD_SEND_SIZELIMIT; + ber_free_buf( ber ); + /* putback, so dumb backends that don't + * check sizelimit won't at least return + * more than expected... */ + op->ors_slimit++; + goto error_return; + } bytes = send_ldap_ber( op->o_conn, ber ); ber_free_buf( ber ); diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 5e59c0b2f9..b6fc42d06a 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -153,6 +153,9 @@ LDAP_BEGIN_DECL /* unknown config file directive */ #define SLAP_CONF_UNKNOWN (-1026) +/* pseudo error code indicating caller should send sizelimitExceeded */ +#define SLAPD_SEND_SIZELIMIT (-1027) + /* We assume "C" locale, that is US-ASCII */ #define ASCII_SPACE(c) ( (c) == ' ' ) #define ASCII_LOWER(c) ( (c) >= 'a' && (c) <= 'z' ) @@ -2252,8 +2255,8 @@ typedef struct slap_overinfo { } slap_overinfo; /* Should successive callbacks in a chain be processed? */ -#define SLAP_CB_FREEME 0x4000 -#define SLAP_CB_CONTINUE 0x8000 +#define SLAP_CB_FREEME 0x04000 +#define SLAP_CB_CONTINUE 0x08000 /* * Paged Results state -- 2.39.5