use hard limit instead of returning adminLimitExceeded when requested limit exceeds hard; improve (and document) syntax; modify test025 accordingly

This commit is contained in:
Pierangelo Masarati 2004-06-22 09:43:41 +00:00
parent 445067260e
commit d8eff4d1b5
4 changed files with 122 additions and 69 deletions

View file

@ -807,8 +807,6 @@ e.g. ldapi:// (and eventually IPSEC). It is not normally used.
Specify the maximum number of entries to return from a search operation.
The default size limit is 500.
Use
.B -1
or
.B unlimited
to specify no limits.
The second format allows a fine grain setting of the size limits.
@ -841,8 +839,6 @@ Specify the maximum number of seconds (in real time)
.B slapd
will spend answering a search request. The default time limit is 3600.
Use
.B -1
or
.B unlimited
to specify no limits.
The second format allows a fine grain setting of the time limits.
@ -1070,21 +1066,22 @@ and
The syntax for time limits is
.BR time[.{soft|hard}]=<integer> ,
where
.BR integer
.I integer
is the number of seconds slapd will spend answering a search request.
If no time limit is explicitly requested by the client, the
.BR soft
limit is used; if the requested time limit exceeds the
.BR hard
limit, an
.I "Administrative limit exceeded"
error is returned.
.\"limit, an
.\".I "Administrative limit exceeded"
.\"error is returned.
limit, the value of the limit is used instead.
If the
.BR hard
limit is set to the keyword
.IR soft ,
the soft limit is used in either case; if it is set to the keyword
.IR none ,
.IR unlimited ,
no hard limit is enforced.
Explicit requests for time limits smaller or equal to the
.BR hard
@ -1093,27 +1090,30 @@ If no limit specifier is set, the value is assigned to the
.BR soft
limit, and the
.BR hard
limit is set to soft, to preserve the original behavior.
limit is set to
.IR soft ,
to preserve the original behavior.
The syntax for size limits is
.BR size[.{soft|hard|unchecked}]=<integer> ,
where
.BR integer
.I integer
is the maximum number of entries slapd will return answering a search
request.
If no size limit is explicitly requested by the client, the
.BR soft
limit is used; if the requested size limit exceeds the
.BR hard
limit, an
.I "Administrative limit exceeded"
error is returned.
.\"limit, an
.\".I "Administrative limit exceeded"
.\"error is returned.
limit, the value of the limit is used instead.
If the
.BR hard
limit is set to the keyword
.IR soft ,
the soft limit is used in either case; if it is set to the keyword
.IR none ,
.IR unlimited ,
no hard limit is enforced.
Explicit requests for size limits smaller or equal to the
.BR hard
@ -1122,12 +1122,21 @@ The
.BR unchecked
specifier sets a limit on the number of candidates a search request is allowed
to examine.
The rationale behind it is that searches for non-properly indicized
attributes may result in large sets of candidates, which must be
examined by
.BR slapd (8)
to determine whether they match the search filter or not.
The
.B unckeched
limit provides a means to drop such operations before they are even
started.
If the selected candidates exceed the
.BR unchecked
limit, the search will abort with
.IR "Unwilling to perform" .
If it is set to the keyword
.IR none ,
.IR unlimited ,
no limit is applied (the default).
If it is set to
.IR disable ,
@ -1137,7 +1146,9 @@ If no limit specifier is set, the value is assigned to the
.BR soft
limit, and the
.BR hard
limit is set to soft, to preserve the original behavior.
limit is set to
.IR soft ,
to preserve the original behavior.
In case of no match, the global limits are used.
The default values are the same of
@ -1157,31 +1168,33 @@ of entries to be returned.
However, the size limit applies to the total count of entries returned within
the search, and not to a single page.
Additional size limits may be enforced; the syntax is
.BR size.pr={<integer>|noEstimate|none} ,
.BR size.pr={<integer>|noEstimate|unlimited} ,
where
.B integer
.I integer
is the max page size if no explicit limit is set; the keyword
.I noEstimate
inhibits the server from returning an estimate of the total number
of entries that might be returned; the keyword
.I none
of entries that might be returned
(note: the current implementation does not return any estimate).
The keyword
.I unlimited
indicates that no limit is applied to the pagedResults control page size.
The syntax
.B size.prtotal={<integer>|none|disabled}
.B size.prtotal={<integer>|unlimited|disabled}
allows to set a limit on the total number of entries that a pagedResults
control allows to return.
By default it is set to the
.B hard
limit.
When set,
.B integer
.I integer
is the max number of entries that the whole search with pagedResults control
can return.
Use
.B none
to allow unlimited number of entries to be returned, i.e. to use
pagedResults as a means to allow clients to circumvent size limitations
on regular searches; the keyword
.I unlimited
to allow unlimited number of entries to be returned, e.g. to allow
the use of the pagedResults control as a means to circumvent size
limitations on regular searches; the keyword
.I disabled
disables the control, i.e. no paged results can be returned.
Note that the total number of entries returned when the pagedResults control

View file

@ -23,6 +23,9 @@
#include "slap.h"
/* define to get an error if requesting limit higher than hard */
#undef ABOVE_HARD_LIMIT_IS_ERROR
static char *
limits2str( unsigned i )
{
@ -734,7 +737,7 @@ limits_parse_one(
arg++;
if ( strncasecmp( arg, "soft=", STRLENOF( "soft=" ) ) == 0 ) {
arg += STRLENOF( "soft=" );
if ( strcasecmp( arg, "none" ) == 0 ) {
if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) {
limit->lms_t_soft = -1;
} else {
@ -750,7 +753,7 @@ limits_parse_one(
}
if ( soft == -1 ) {
/* FIXME: use "none" instead */
/* FIXME: use "unlimited" instead; issue warning? */
}
limit->lms_t_soft = soft;
@ -761,7 +764,7 @@ limits_parse_one(
if ( strcasecmp( arg, "soft" ) == 0 ) {
limit->lms_t_hard = 0;
} else if ( strcasecmp( arg, "none" ) == 0 ) {
} else if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) {
limit->lms_t_hard = -1;
} else {
@ -777,7 +780,7 @@ limits_parse_one(
}
if ( hard == -1 ) {
/* FIXME: use "none" instead */
/* FIXME: use "unlimited" instead */
}
if ( hard == 0 ) {
@ -793,7 +796,7 @@ limits_parse_one(
} else if ( arg[0] == '=' ) {
arg++;
if ( strcasecmp( arg, "none" ) == 0 ) {
if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) {
limit->lms_t_soft = -1;
} else {
@ -817,7 +820,7 @@ limits_parse_one(
arg++;
if ( strncasecmp( arg, "soft=", STRLENOF( "soft=" ) ) == 0 ) {
arg += STRLENOF( "soft=" );
if ( strcasecmp( arg, "none" ) == 0 ) {
if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) {
limit->lms_s_soft = -1;
} else {
@ -833,7 +836,7 @@ limits_parse_one(
}
if ( soft == -1 ) {
/* FIXME: use "none" instead */
/* FIXME: use "unlimited" instead */
}
limit->lms_s_soft = soft;
@ -844,7 +847,7 @@ limits_parse_one(
if ( strcasecmp( arg, "soft" ) == 0 ) {
limit->lms_s_hard = 0;
} else if ( strcasecmp( arg, "none" ) == 0 ) {
} else if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) {
limit->lms_s_hard = -1;
} else {
@ -860,7 +863,7 @@ limits_parse_one(
}
if ( hard == -1 ) {
/* FIXME: use "none" instead */
/* FIXME: use "unlimited" instead */
}
if ( hard == 0 ) {
@ -872,7 +875,7 @@ limits_parse_one(
} else if ( strncasecmp( arg, "unchecked=", STRLENOF( "unchecked=" ) ) == 0 ) {
arg += STRLENOF( "unchecked=" );
if ( strcasecmp( arg, "none" ) == 0 ) {
if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) {
limit->lms_s_unchecked = -1;
} else if ( strcasecmp( arg, "disabled" ) == 0 ) {
@ -891,7 +894,7 @@ limits_parse_one(
}
if ( unchecked == -1 ) {
/* FIXME: use "none" instead */
/* FIXME: use "unlimited" instead */
}
limit->lms_s_unchecked = unchecked;
@ -902,7 +905,7 @@ limits_parse_one(
if ( strcasecmp( arg, "noEstimate" ) == 0 ) {
limit->lms_s_pr_hide = 1;
} else if ( strcasecmp( arg, "none" ) == 0 ) {
} else if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) {
limit->lms_s_pr = -1;
} else {
@ -918,7 +921,7 @@ limits_parse_one(
}
if ( pr == -1 ) {
/* FIXME: use "none" instead */
/* FIXME: use "unlimited" instead */
}
limit->lms_s_pr = pr;
@ -927,7 +930,7 @@ limits_parse_one(
} else if ( strncasecmp( arg, "prtotal=", STRLENOF( "prtotal=" ) ) == 0 ) {
arg += STRLENOF( "prtotal=" );
if ( strcasecmp( arg, "none" ) == 0 ) {
if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) {
limit->lms_s_pr_total = -1;
} else if ( strcasecmp( arg, "disabled" ) == 0 ) {
@ -950,7 +953,7 @@ limits_parse_one(
}
if ( total == -1 ) {
/* FIXME: use "none" instead */
/* FIXME: use "unlimited" instead */
}
if ( total == 0 ) {
@ -966,7 +969,7 @@ limits_parse_one(
} else if ( arg[0] == '=' ) {
arg++;
if ( strcasecmp( arg, "none" ) == 0 ) {
if ( strcasecmp( arg, "unlimited" ) == 0 || strcasecmp( arg, "none" ) == 0 ) {
limit->lms_s_soft = -1;
} else {
@ -1040,6 +1043,7 @@ limits_check( Operation *op, SlapReply *rs )
}
} else if ( op->ors_limit->lms_t_hard > 0 ) {
#ifdef ABOVE_HARD_LIMIT_IS_ERROR
if ( op->ors_tlimit == SLAP_MAX_LIMIT ) {
op->ors_tlimit = op->ors_limit->lms_t_hard;
@ -1050,6 +1054,11 @@ limits_check( Operation *op, SlapReply *rs )
rs->sr_err = LDAP_SUCCESS;
return -1;
}
#else /* ! ABOVE_HARD_LIMIT_IS_ERROR */
if ( op->ors_tlimit > op->ors_limit->lms_t_hard ) {
op->ors_tlimit = op->ors_limit->lms_t_hard;
}
#endif /* ! ABOVE_HARD_LIMIT_IS_ERROR */
}
}
@ -1105,6 +1114,7 @@ limits_check( Operation *op, SlapReply *rs )
slimit = op->ors_slimit - op->o_pagedresults_state.ps_count;
}
#ifdef ABOVE_HARD_LIMIT_IS_ERROR
} else if ( pr_total > 0 && op->ors_slimit != SLAP_MAX_LIMIT
&& ( op->ors_slimit == SLAP_NO_LIMIT || op->ors_slimit > pr_total ) )
{
@ -1112,6 +1122,7 @@ limits_check( Operation *op, SlapReply *rs )
send_ldap_result( op, rs );
rs->sr_err = LDAP_SUCCESS;
return -1;
#endif /* ! ABOVE_HARD_LIMIT_IS_ERROR */
} else {
/* if no limit is required, use soft limit */
@ -1121,8 +1132,13 @@ limits_check( Operation *op, SlapReply *rs )
/* first round of pagedResults: set count to any appropriate limit */
/* if the limit is set, check that it does not violate any server-side limit */
#ifdef ABOVE_HARD_LIMIT_IS_ERROR
if ( op->ors_slimit == SLAP_MAX_LIMIT ) {
slimit2 = op->ors_slimit = pr_total;
#else /* ! ABOVE_HARD_LIMIT_IS_ERROR */
if ( op->ors_slimit == SLAP_MAX_LIMIT || op->ors_slimit > pr_total ) {
slimit2 = op->ors_slimit = pr_total;
#endif /* ! ABOVE_HARD_LIMIT_IS_ERROR */
} else if ( op->ors_slimit == 0 ) {
slimit2 = pr_total;
@ -1196,6 +1212,7 @@ limits_check( Operation *op, SlapReply *rs )
/* explicit hard limit: error if violated */
} else if ( op->ors_limit->lms_s_hard > 0 ) {
#ifdef ABOVE_HARD_LIMIT_IS_ERROR
if ( op->ors_slimit == SLAP_MAX_LIMIT ) {
op->ors_slimit = op->ors_limit->lms_s_hard;
@ -1206,6 +1223,11 @@ limits_check( Operation *op, SlapReply *rs )
rs->sr_err = LDAP_SUCCESS;
return -1;
}
#else /* ! ABOVE_HARD_LIMIT_IS_ERROR */
if ( op->ors_slimit > op->ors_limit->lms_s_hard ) {
op->ors_slimit = op->ors_limit->lms_s_hard;
}
#endif /* ! ABOVE_HARD_LIMIT_IS_ERROR */
}
}

View file

@ -43,18 +43,18 @@ rootpw secret
#hdb#index uid eq
# Need extra limits for pagedResults on backends that support it...
#bdb#limits dn.exact="cn=Unlimited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.pr=none
#bdb#limits dn.exact="cn=Unlimited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.pr=unlimited
#bdb#limits dn.exact="cn=Page Size Limited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.pr=4
#bdb#limits dn.exact="cn=Paged Results Disabled User,ou=Paged Results Users,dc=example,dc=com" size=4 size.prtotal=disabled
#bdb#limits dn.exact="cn=Paged Results Limited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.prtotal=10
#hdb#limits dn.exact="cn=Unlimited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.pr=none
#hdb#limits dn.exact="cn=Unlimited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.pr=unlimited
#hdb#limits dn.exact="cn=Page Size Limited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.pr=4
#hdb#limits dn.exact="cn=Paged Results Disabled User,ou=Paged Results Users,dc=example,dc=com" size=4 size.prtotal=disabled
#hdb#limits dn.exact="cn=Paged Results Limited User,ou=Paged Results Users,dc=example,dc=com" size=4 size.prtotal=10
limits dn.exact="cn=Unlimited User,ou=People,dc=example,dc=com" size=none time=none
limits dn.exact="cn=Soft Limited User,ou=People,dc=example,dc=com" size.soft=4 size.hard=none
limits dn.exact="cn=Unlimited User,ou=People,dc=example,dc=com" size=unlimited time=unlimited
limits dn.exact="cn=Soft Limited User,ou=People,dc=example,dc=com" size.soft=4 size.hard=unlimited
limits dn.exact="cn=Hard Limited User,ou=People,dc=example,dc=com" size.soft=4 size.hard=8
limits dn.exact="cn=Unchecked Limited User,ou=People,dc=example,dc=com" size.unchecked=4
limits group="cn=Unchecked Limited Users,ou=Groups,dc=example,dc=com" size.unchecked=4

View file

@ -406,13 +406,23 @@ case $RC in
fi
;;
4)
echo "...error: bumped into server-side size limit instead of hard size administrative limit"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
;;
11)
echo "...bumped into server-side hard size administrative limit"
if test x"$COUNT" != x ; then
if test "$COUNT" = "$SIZELIMIT" ; then
echo "...error: bumped into requested ($SIZELIMIT) size limit"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
else
echo "...got size limit $COUNT instead of requested $SIZELIMIT entries"
fi
else
echo "...error: bumped into server-side size limit, but got no entries!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
;;
# 11)
# echo "...bumped into server-side hard size administrative limit"
# ;;
*)
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
@ -446,9 +456,9 @@ case $RC in
exit $RC
fi
;;
11)
echo "...bumped into server-side hard size administrative limit"
;;
# 11)
# echo "...bumped into server-side hard size administrative limit"
# ;;
*)
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
@ -1037,18 +1047,20 @@ case $RC in
if test x"$COUNT" != x ; then
if test "$COUNT" = "$SIZELIMIT" ; then
echo "...error: bumped into requested ($SIZELIMIT) size limit"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
else
echo "...error: got size limit $SIZELIMIT but $COUNT entries"
echo "...got size limit $COUNT instead of requested $SIZELIMIT entries"
fi
else
echo "...error: bumped into server-side size limit, but got no entries!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
;;
11)
echo "...bumped into hard size administrative limit"
;;
# 11)
# echo "...bumped into hard size administrative limit"
# ;;
*)
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
@ -1074,11 +1086,17 @@ case $RC in
fi
;;
4)
echo "...bumped into requested ($SIZELIMIT=$COUNT) size limit"
;;
11)
echo "...bumped into hard size administrative limit"
if test x"$COUNT" != x ; then
echo "...bumped into requested ($SIZELIMIT=$COUNT) size limit"
else
echo "...error: bumped into size limit but got no entries!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
;;
# 11)
# echo "...bumped into hard size administrative limit"
# ;;
*)
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
@ -1102,9 +1120,9 @@ case $RC in
exit $RC
fi
;;
11)
echo "...bumped into unchecked administrative limit"
;;
# 11)
# echo "...bumped into unchecked administrative limit"
# ;;
*)
echo "ldapsearch failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS