ldap/servers/slapd/modify.c | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
New commits:
commit 1980427b8c78e79982c056ac270c6c3b11188830
Author: Rich Megginson <rmeggins(a)redhat.com>
Date: Wed Feb 9 14:54:29 2011 -0700
Bug 675320 - empty modify operation with repl on or lastmod off will crash server
https://bugzilla.redhat.com/show_bug.cgi?id=675320
Resolves: bug 675320
Bug Description: empty modify operation with repl on or lastmod off will crash server
Reviewed by: nkinder, nhosoi (Thanks!)
Branch: master
Fix Description: Check the modifications after lastmod is applied, if any.
If there are still no mods to apply, just return LDAP_SUCCESS to the client
and end the modify request. This makes it so that an empty modify is
allowed, but no further processing is done to avoid code that may not deal
with mods == NULL.
I also found a problem with the way an empty modify was handled. OpenLDAP
does not return an explicit error code if there was a problem reading the
sequence of modify ops, so we have to resort to other checking. This allows
an empty modify to pass through, when using either mozldap or openldap.
Platforms tested: RHEL5 x86_64, RHEL6 x86_64
Flag Day: no
Doc impact: no
diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c
index 756ab6b..51d9f48 100644
--- a/ldap/servers/slapd/modify.c
+++ b/ldap/servers/slapd/modify.c
@@ -303,12 +303,33 @@ do_modify( Slapi_PBlock *pb )
}
/* check for decoding error */
- if ( (tag != LBER_END_OF_SEQORSET) && (len != -1) )
+ /*
+ if using mozldap - will return LBER_END_OF_SEQORSET if loop
+ completed successfully, otherwise, other value
+ if using openldap - will return LBER_DEFAULT in either case
+ if there was at least one element read, len will be -1
+ if there were no elements read (empty modify) len will be 0
+ */
+#if defined(USE_OPENLDAP)
+ if ( tag != LBER_END_OF_SEQORSET )
+ {
+ if ( ( len == 0 ) && ( 0 == smods.num_elements ) && !ignored_some_mods
) {
+ /* ok - empty modify - allow empty modifies */
+ } else if ( len != -1 ) {
+ op_shared_log_error_access (pb, "MOD", dn, "decoding error");
+ send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0, NULL
);
+ goto free_and_return;
+ }
+ /* else ok */
+ }
+#else
+ if ( tag != LBER_END_OF_SEQORSET )
{
op_shared_log_error_access (pb, "MOD", dn, "decoding error");
send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "decoding error", 0, NULL
);
goto free_and_return;
}
+#endif
/* decode the optional controls - put them in the pblock */
if ( (err = get_ldapmessage_controls( pb, ber, NULL )) != 0 )
@@ -728,7 +749,14 @@ static void op_shared_modify (Slapi_PBlock *pb, int pw_change, char
*old_pw)
if (!repl_op && !skip_modified_attrs && lastmod)
{
modify_update_last_modified_attr(pb, &smods);
- }
+ }
+
+ if (0 == slapi_mods_get_num_mods(&smods)) {
+ /* nothing to do - no mods - this is not an error - just
+ send back LDAP_SUCCESS */
+ send_ldap_result(pb, LDAP_SUCCESS, NULL, NULL, 0, NULL);
+ goto free_and_return;
+ }
/*
* Add the unhashed password pseudo-attribute before