If you perform a ModDN operation with a DN consisting of nothing but 100,000 ',' characters (a very badly formed DN, to be sure), the dn2ancestor code will happily traverse back through the entire DN one comma at a time looking for an existing parent of the entry using dn2entry. What's worse, it uses recursion to do so (dn2ancestor -> dn2ancestor_or_entry -> dn2ancestor -> etc.), chewing up CPU and finally all of the RAM causing an OOM exit.
Created attachment 123785 [details] files for fix
Created attachment 123786 [details] diffs for fix
Note of CVE name: CVE-2006-0452: A carefully crafted malformed DN will cause the server to recurse until it runs out of memory and exits
Reviewed by: All (Thanks!) Files: https://bugzilla.redhat.com/bugzilla/attachment.cgi?id=123785 Branch: HEAD Fix Description: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=179137#c0 The fix looks scary, but I thought it would be best to get rid of recursion entirely (ugh - recursion in a multi threaded server - this isn't lisp . . .). Along with eliminating recursion, I created a new function called slapi_dn_find_parent that just returns a pointer to the beginning of the parent of the given dn, rather than returning a copy (as in slapi_dn_parent), to eliminate malloc/free in cases where it is unnecessary such as iterating through the parents in an DN. The new function is basically just the guts of slapi_dn_parent with one twist, specifically to address the bug in question - it skips through consecutive runs of DN separator characters. We should probably have a function like const char *slapi_dn_is_valid(const char *) that returns NULL if the given DN is valid or returns a pointer to the first invalid character if not. We could probably save a lot of time in processing bad or malicious client requests. Anyway, back to dn2ancestor. The given ancestordn must contain the _unnormalized_ parent DN, since some clients get irritated when they get back an DN in a different form than given. However, we need to have a normalized DN to pass to dn2entry, and we cannot use a single Slapi_DN that has both a dn and a ndn that are passed in byval (unless we add a new API or skip the API altogether), so the variable ancestorndn holds the normalized DN. Using the original pointer to the given sdn also allows us to avoid malloc/free entirely. Platforms tested: Fedora Core 4 Flag Day: no Doc impact: no QA impact: should be covered by regular nightly and manual testing New Tests integrated into TET: We need a test case that calls moddn and modify operations with really bad DNs, consisting of nothing but thousands of ',', '+', and '=' chars. Checking in ldapserver/ldap/servers/slapd/dn.c; /cvs/dirsec/ldapserver/ldap/servers/slapd/dn.c,v <-- dn.c new revision: 1.8; previous revision: 1.7 done Checking in ldapserver/ldap/servers/slapd/slapi-plugin.h; /cvs/dirsec/ldapserver/ldap/servers/slapd/slapi-plugin.h,v <-- slapi-plugin.h new revision: 1.9; previous revision: 1.8 done Checking in ldapserver/ldap/servers/slapd/back-ldbm/dn2entry.c; /cvs/dirsec/ldapserver/ldap/servers/slapd/back-ldbm/dn2entry.c,v <-- dn2entry.c new revision: 1.5; previous revision: 1.4 done
Verified DS 6.21 SP3 20060310.1
Somehow the errata system did not automatically close these bugs even though DS SP 2 is shipped and available live on RHN
trying to manually close
trying again