From eb900d4ac34f4049b4a1716722db1287d0a6a29f Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Sun, 17 Jan 2016 15:57:53 +0100 Subject: Fix freeing of DN of Slapi_Entry Add entry_set_dn to set a new DN and free the memory of the both copies inside the Slapi_Entry. This currently uses an ugly hack and makes assumptions about internal data structures. --- service_passwords.c | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/service_passwords.c b/service_passwords.c index 316cfc7..9e42bab 100644 --- a/service_passwords.c +++ b/service_passwords.c @@ -290,6 +290,43 @@ static int auth_with_password_fallback(char *dn, struct berval *credentials) return 1; } +/** Free the memory of the current DN of an \c Slapi_Entry and set a new DN. + * + * This function update the DN in the supplied \c Slapi_Entry. In ontrast to the + * \c slapi_entry_set_dn method, it tries to free the memory of the old DN. It + * is a bit difficult because the DN is stored twice inside the \c Slapi_Entry + * and there is only a method to get a reference to one of the values. So this + * function tries do guess the memory layout of the \c Slapi_Entry and only + * calls free on the second copy if the memory position of the first entry is + * like the expected position. + * + * @param[in,out] entry The \c Slapi_Entry to manipulate. + * @param[in] dn The new DN to set in the entry. The value is copied into the + * entry, so the caller have to free the memory afterwards. + */ +static void entry_set_dn(Slapi_Entry *entry, char *dn) +{ + char *old_dn = NULL; + + /* This is save. */ + old_dn = slapi_entry_get_dn(entry); + slapi_ch_free_string(&old_dn); + + /* Try to gess the layout of Slapi_Entry because there is no slapi method + to get a reference to the e_nname value. This might break with other + versions of openldap. */ + struct Entry { + unsigned long e_id; + struct berval e_name; + struct berval e_nname; + }; + if (((struct Entry*)entry)->e_name.bv_val == old_dn) { + slapi_ch_free_string(&((struct Entry*)entry)->e_nname.bv_val); + } + + slapi_entry_set_dn(entry, dn); +} + /** \c PRE_BIND plugin to allow password fallback. * * This function is called before a bind operation. If the BIND_DN is a user @@ -475,18 +512,14 @@ static int pre_entry(Slapi_PBlock *pb) /* modify the dn of the returned entry */ if (dn_contains_uid(result_dn) == 0) { - /* TODO: style */ - new_entry = slapi_entry_dup(entry); - ber_bvfree(new_entry->e_name); - ber_bvfree(new_entry->e_nname); - snprintf(rdn, 254, "cn=%s", service); new_dn = slapi_dn_plus_rdn(result_dn, rdn); - slapi_entry_set_dn(new_entry, new_dn); + + new_entry = slapi_entry_dup(entry); + entry_set_dn(new_entry, new_dn); slapi_ch_free_string(&new_dn); slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, new_entry); - slapi_entry_free(entry); } fail1: -- cgit v1.2.3-1-g7c22