summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Sulfrian <alex@spline.inf.fu-berlin.de>2016-01-17 15:57:53 +0100
committerAlexander Sulfrian <alex@spline.inf.fu-berlin.de>2016-01-17 15:57:53 +0100
commiteb900d4ac34f4049b4a1716722db1287d0a6a29f (patch)
treeaa36ef06b65156ec0eb579e34acb3905768bb094
parent5fd72e46773800cc556c342583c2ef9212adb2dd (diff)
downloadldap-plugin-eb900d4ac34f4049b4a1716722db1287d0a6a29f.tar.gz
ldap-plugin-eb900d4ac34f4049b4a1716722db1287d0a6a29f.tar.bz2
ldap-plugin-eb900d4ac34f4049b4a1716722db1287d0a6a29f.zip
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.
-rw-r--r--service_passwords.c47
1 files 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: