From d6979fcc40e00fd6ddd393c724cd728349b86de8 Mon Sep 17 00:00:00 2001 From: "Francisco Blas (klondike) Izquierdo Riera" Date: Tue, 16 Dec 2014 07:12:26 +0100 Subject: [PATCH] Allow LDAP modifications for entry creation Heimdal will refuse to create new entries when an entry already exists even if said entry has no kerberos info and is a new entry. This patch fixes this issue by allowing object modifications even if the flags disallow them when we are inserting a new principal on the database. Signed-off-by: Francisco Blas Izquierdo Riera (klondike) --- lib/hdb/hdb-ldap.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/hdb/hdb-ldap.c b/lib/hdb/hdb-ldap.c index 9ce4ba74f..18ecc1067 100644 --- a/lib/hdb/hdb-ldap.c +++ b/lib/hdb/hdb-ldap.c @@ -389,10 +389,10 @@ bervalstrcmp(struct berval *v, const char *str) static krb5_error_code LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, - LDAPMessage * msg, LDAPMod *** pmods) + LDAPMessage * msg, LDAPMod *** pmods, krb5_boolean *pis_new_entry) { krb5_error_code ret; - krb5_boolean is_new_entry; + krb5_boolean is_new_entry = FALSE; char *tmp = NULL; LDAPMod **mods = NULL; hdb_entry_ex orig; @@ -414,8 +414,6 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, if (ret) goto out; - is_new_entry = FALSE; - vals = ldap_get_values_len(HDB2LDAP(db), msg, "objectClass"); if (vals) { int num_objectclasses = ldap_count_values_len(vals); @@ -454,12 +452,12 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, * orig being intiialized to zero */ memset(&orig, 0, sizeof(orig)); - ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "top"); - if (ret) - goto out; - /* account is the structural object class */ if (is_account == FALSE) { + ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "top"); + if (ret) + goto out; + ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", structural_object); is_account = TRUE; @@ -759,6 +757,8 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, out: + *pis_new_entry = is_new_entry; + if (ret == 0) *pmods = mods; else if (mods != NULL) { @@ -1737,6 +1737,7 @@ LDAP_store(krb5_context context, HDB * db, unsigned flags, int rc; LDAPMessage *msg = NULL, *e = NULL; char *dn = NULL, *name = NULL; + krb5_boolean is_new_entry; if ((flags & HDB_F_PRECHECK)) return 0; /* we can't guarantee whether we'll be able to perform it */ @@ -1756,7 +1757,7 @@ LDAP_store(krb5_context context, HDB * db, unsigned flags, goto out; /* turn new entry into LDAPMod array */ - ret = LDAP_entry2mods(context, db, entry, e, &mods); + ret = LDAP_entry2mods(context, db, entry, e, &mods, &is_new_entry); if (ret) goto out; @@ -1767,8 +1768,9 @@ LDAP_store(krb5_context context, HDB * db, unsigned flags, krb5_set_error_message(context, ret, "asprintf: out of memory"); goto out; } - } else if (flags & HDB_F_REPLACE) { + } else if ((flags & HDB_F_REPLACE) || (is_new_entry)) { /* Entry exists, and we're allowed to replace it. */ + /* Entry may also exist but need to be modified to create a new principal. */ dn = ldap_get_dn(HDB2LDAP(db), e); } else { /* Entry exists, but we're not allowed to replace it. Bail. */ @@ -1847,6 +1849,8 @@ LDAP_remove(krb5_context context, HDB *db, goto out; } + /* HACK: This should check if we need to delete the object or just some attributes */ + rc = ldap_delete_ext_s(HDB2LDAP(db), dn, NULL, NULL ); if (check_ldap(context, db, rc)) { ret = HDB_ERR_CANT_LOCK_DB;