Fix NULL pointer dereference in LDAP lookup code.
[claws.git] / src / ldapupdate.c
index 47472ca989e9679e76ef6e5a37b37bb5d5054f1a..e8ea64ae2779012888f1c841ba1a8ba7b2a3c0f5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2003-2007 Michael Rasmussen and the Claws Mail team
+ * Copyright (C) 2003-2012 Michael Rasmussen and the Claws Mail team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -35,6 +35,7 @@
 
 #ifdef HAVE_CONFIG_H
 #  include "config.h"
+#include "claws-features.h"
 #endif
 
 #ifdef USE_LDAP
@@ -43,8 +44,6 @@
 #include <glib/gi18n.h>
 #include <sys/time.h>
 #include <string.h>
-#include <ldap.h>
-#include <lber.h>
 
 #include "ldapupdate.h"
 #include "mgutils.h"
@@ -96,7 +95,7 @@ struct _Rdn {
  */
 void ldapsvr_retrieve_item_group(ItemGroup *group, GHashTable *array) {
        /* Not implemented in this release */
-       g_return_if_fail(group != NULL);
+       cm_return_if_fail(group != NULL);
 }
 
 /**
@@ -150,7 +149,7 @@ void attrkeyvalue_free(AttrKeyValue *akv) {
  */
 EmailKeyValue *ldapsvr_retrieve_item_email(ItemEMail *item) {
        EmailKeyValue *newItem;
-       g_return_val_if_fail(item != NULL, NULL);
+       cm_return_val_if_fail(item != NULL, NULL);
        newItem = emailkeyvalue_create();               
        newItem->alias = g_strdup(ADDRITEM_NAME(item));
        newItem->mail = g_strdup(item->address);
@@ -165,7 +164,7 @@ EmailKeyValue *ldapsvr_retrieve_item_email(ItemEMail *item) {
  */
 AttrKeyValue *ldapsvr_retrieve_attribute(UserAttribute *item) {
        AttrKeyValue *newItem;
-       g_return_val_if_fail(item != NULL, NULL);
+       cm_return_val_if_fail(item != NULL, NULL);
        newItem = attrkeyvalue_create();
        newItem->key = g_strdup(item->name);
        newItem->value = g_strdup(item->value);
@@ -181,13 +180,13 @@ AttrKeyValue *ldapsvr_retrieve_attribute(UserAttribute *item) {
 gboolean ldapsvr_retrieve_item_person(ItemPerson *person, GHashTable *array) {
        GList *node, *attr;
 
-       g_return_val_if_fail(person != NULL, FALSE);
+       cm_return_val_if_fail(person != NULL, FALSE);
        switch (person->status) {
                case NONE: return FALSE;
                case ADD_ENTRY: g_hash_table_insert(array, "status", "new"); break;
                case UPDATE_ENTRY: g_hash_table_insert(array, "status", "update"); break;
                case DELETE_ENTRY: g_hash_table_insert(array, "status", "delete"); break;
-               default: g_critical(_("ldapsvr_retrieve_item_person->Unknown status: %d"), person->status);
+               default: g_critical("ldapsvr_retrieve_item_person->Unknown status: %d", person->status);
        }
        g_hash_table_insert(array, "uid", ADDRITEM_ID(person));
        g_hash_table_insert(array, "cn", ADDRITEM_NAME(person));
@@ -195,6 +194,7 @@ gboolean ldapsvr_retrieve_item_person(ItemPerson *person, GHashTable *array) {
        g_hash_table_insert(array, "sn", person->lastName);
        g_hash_table_insert(array, "nickName", person->nickName);
        g_hash_table_insert(array, "dn", person->externalID);
+       g_hash_table_insert(array, "person", person);
        node = person->listEMail;
        attr = NULL;
        while (node) {
@@ -232,15 +232,15 @@ void ldapsvr_print_contacts_hashtable(gpointer key, gpointer data, gpointer fd)
                while (node) {
                        EmailKeyValue *item = node->data;
                        if (debug_get_mode()) {
-                               debug_print("\t\talias = %s\n", item->alias);
-                               debug_print("\t\tmail = %s\n", item->mail);
-                               debug_print("\t\tremarks = %s\n", item->remarks);
+                               debug_print("\t\talias = %s\n", item->alias?item->alias:"null");
+                               debug_print("\t\tmail = %s\n", item->mail?item->mail:"null");
+                               debug_print("\t\tremarks = %s\n", item->remarks?item->remarks:"null");
                        }
                        else if (fd) {
                                FILE *stream = (FILE *) fd;
-                               fprintf(stream, "\t\talias = %s\n", item->alias);
-                               fprintf(stream, "\t\tmail = %s\n", item->mail);
-                               fprintf(stream, "\t\tremarks = %s\n", item->remarks);
+                               fprintf(stream, "\t\talias = %s\n", item->alias?item->alias:"null");
+                               fprintf(stream, "\t\tmail = %s\n", item->mail?item->mail:"null");
+                               fprintf(stream, "\t\tremarks = %s\n", item->remarks?item->remarks:"null");
                        }
                        node = g_list_next(node);
                }
@@ -250,21 +250,23 @@ void ldapsvr_print_contacts_hashtable(gpointer key, gpointer data, gpointer fd)
                while (node) {
                        AttrKeyValue *item = node->data;
                        if (debug_get_mode()) {
-                               debug_print("\t\t%s = %s\n", item->key, item->value);
+                               debug_print("\t\t%s = %s\n", item->key?item->key:"null",
+                                               item->value?item->value:"null");
                        }
                        else if (fd) {
                                FILE *stream = (FILE *) fd;
-                               fprintf(stream, "\t\t%s = %s\n", item->key, item->value);
+                               fprintf(stream, "\t\t%s = %s\n", item->key?item->key:"null",
+                                               item->value?item->value:"null");
                        }
                        node = g_list_next(node);
                }
        }
        else {
                if (debug_get_mode())
-                       debug_print("\t\t%s = %s\n", keyName, (gchar *) data);
+                       debug_print("\t\t%s = %s\n", keyName?keyName:"null", data?(gchar *)data:"null");
                else if (fd) {
                        FILE *stream = (FILE *) fd;
-                       fprintf(stream, "\t\t%s = %s\n", keyName, (gchar *) data);
+                       fprintf(stream, "\t\t%s = %s\n", keyName?keyName:"null", data?(gchar *)data:"null");
                }
        }
 }
@@ -294,7 +296,7 @@ void ldapsvr_free_hashtable(GList *list) {
  */
 ItemPerson *ldapsvr_get_contact(LdapServer *server, gchar *uid) {
        AddrItemObject *aio;
-       g_return_val_if_fail(server != NULL || uid != NULL, NULL);
+       cm_return_val_if_fail(server != NULL || uid != NULL, NULL);
        aio = addrcache_get_object(server->addressCache, uid);
        if (aio) {
                if(aio->type == ITEMTYPE_PERSON) {
@@ -304,76 +306,6 @@ ItemPerson *ldapsvr_get_contact(LdapServer *server, gchar *uid) {
        return NULL;
 }
 
-/**
- * Connect to LDAP server.
- * \param  ctl Control object to process.
- * \return LDAP Resource to LDAP.
- */
-LDAP *ldapsvr_connect(LdapControl *ctl) {
-       LDAP *ld = NULL;
-       gint rc;
-       gint version;
-       gchar *uri = NULL;
-
-       g_return_val_if_fail(ctl != NULL, NULL);
-
-       uri = g_strdup_printf("ldap%s://%s:%d",
-                               ctl->enableSSL?"s":"",
-                               ctl->hostName, ctl->port);
-       ldap_initialize(&ld, uri);
-       g_free(uri);
-
-       if (ld == NULL)
-               return NULL;
-
-       debug_print("connected to LDAP host %s on port %d\n", ctl->hostName, ctl->port);
-
-#ifdef USE_LDAP_TLS
-       /* Handle TLS */
-       version = LDAP_VERSION3;
-       rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
-       if (rc == LDAP_OPT_SUCCESS) {
-               ctl->version = LDAP_VERSION3;
-       }
-
-       if (ctl->version == LDAP_VERSION3) {
-               if (ctl->enableTLS && !ctl->enableSSL) {
-                       rc = ldap_start_tls_s(ld, NULL, NULL);
-                       
-                       if (rc != LDAP_SUCCESS) {
-                               g_printerr("LDAP Error(tls): ldap_simple_bind_s: %s\n",
-                                       ldap_err2string(rc));
-                               return NULL;
-                       }
-               }
-       }
-#endif
-
-       /* Bind to the server, if required */
-       if (ctl->bindDN) {
-               if (* ctl->bindDN != '\0') {
-                       rc = claws_ldap_simple_bind_s(ld, ctl->bindDN, ctl->bindPass);
-                       if (rc != LDAP_SUCCESS) {
-                               g_printerr("bindDN: %s, bindPass: %s\n", ctl->bindDN, ctl->bindPass);
-                               g_printerr("LDAP Error(bind): ldap_simple_bind_s: %s\n",
-                                       ldap_err2string(rc));
-                               return NULL;
-                       }
-               }
-       }
-       return ld;
-}
-
-/**
- * Disconnect to LDAP server.
- * \param ld Resource to LDAP.
- */
-void ldapsvr_disconnect(LDAP *ld) {
-       /* Disconnect */
-       g_return_if_fail(ld != NULL);
-       ldap_unbind_ext(ld, NULL, NULL);
-}
-
 /**
  * Create an initial Rdn structure
  *
@@ -419,7 +351,7 @@ void rdn_free(Rdn *rdn) {
  */
 void update_rdn(Rdn *rdn, gchar *head, gchar *tail) {
        rdn->value = g_strdup(head);
-       rdn->new_dn = g_strdup_printf("mail=%s%s", head, tail);
+       rdn->new_dn = g_strdup_printf("%s=%s%s", rdn->attribute, head, tail);
 }
 
 /**
@@ -434,13 +366,14 @@ Rdn *ldapsvr_modify_dn(GHashTable *hash, gchar *dn) {
        gchar *pos, *compare;
        gchar *rest;
        gchar *val;
-       g_return_val_if_fail(hash != NULL || dn != NULL, NULL);
+       cm_return_val_if_fail(hash != NULL || dn != NULL, NULL);
        
        pos = g_strstr_len(dn, strlen(dn), "=");
-       compare = g_strndup(dn, pos - dn);
-
        if (!pos)
                return NULL;
+
+       compare = g_strndup(dn, pos - dn);
+
        pos++;
        rest = g_strstr_len(pos, strlen(pos), ",");
        val = g_strndup(pos, rest - pos);
@@ -450,17 +383,16 @@ Rdn *ldapsvr_modify_dn(GHashTable *hash, gchar *dn) {
                return NULL;
        }
        rdn = rdn_create();
-       rdn->value = g_strdup(val);
-       rdn->attribute = g_strdup(compare);
-       g_free(val);
+       rdn->value = val;
+       rdn->attribute = compare;
+
        if (strcmp("mail", rdn->attribute) == 0) {
                GList *list = g_hash_table_lookup(hash, rdn->attribute);
                while (list) {
                        EmailKeyValue *item = list->data;
-                       compare = g_strdup((gchar *) item->mail);
+                       compare = (gchar *) item->mail;
                        if (strcmp(compare, rdn->value) == 0) {
                                update_rdn(rdn, compare, rest);
-                               g_free(compare);
                                return rdn;
                        }
                        list = g_list_next(list);
@@ -469,28 +401,16 @@ Rdn *ldapsvr_modify_dn(GHashTable *hash, gchar *dn) {
                if (strcmp(compare, rdn->attribute) != 0) {
                        /* RDN changed. Find new */
                        update_rdn(rdn, compare, rest);
-                       g_free(compare);
                        return rdn;
                }
-               else {
-                       /* We cannot remove dn */
-                       g_free(compare);
-                       rdn_free(rdn);
-                       return NULL;
-               }
        }
        else {
                compare = g_hash_table_lookup(hash, rdn->attribute);
                /* if compare and rdn->attribute are equal then dn removed/empty */
-               if (strcmp(compare, rdn->attribute) != 0) {
+               if (compare != NULL && strcmp(compare, rdn->attribute) != 0) {
                        update_rdn(rdn, compare, rest);
                        return rdn;
                }
-               else {
-                       /* We cannot remove dn */
-                       rdn_free(rdn);
-                       return NULL;
-               }
        }
        rdn_free(rdn);
        return NULL;
@@ -549,7 +469,7 @@ void clean_up(LDAP *ld, LdapServer *server, GHashTable *contact) {
                        ItemPerson *res = 
                                addrcache_remove_person(server->addressCache, person);
                        if (!res)
-                               g_critical(N_("ldapsvr_update_book: Could not clean cache\n"));
+                               g_critical("ldapsvr_update_book: Could not clean cache\n");
                        else
                                addritem_free_item_person(res);
                }
@@ -570,7 +490,7 @@ AttrKeyValue *get_cn(gchar *dn) {
        gchar *end;
        gchar *item;
        gchar **key_value;
-       g_return_val_if_fail(dn != NULL, NULL);
+       cm_return_val_if_fail(dn != NULL, NULL);
        
        cn = attrkeyvalue_create();
        start = g_strstr_len(dn, strlen(dn), "cn");
@@ -604,7 +524,7 @@ AttrKeyValue *get_mail(gchar *dn) {
        gchar *end;
        gchar *item;
        gchar **key_value;
-       g_return_val_if_fail(dn != NULL, NULL);
+       cm_return_val_if_fail(dn != NULL, NULL);
        
        mail = attrkeyvalue_create();
        start = g_strstr_len(dn, strlen(dn), "mail");
@@ -639,7 +559,7 @@ AttrKeyValue *get_ou(gchar *dn) {
        gchar *item;
        gchar **key_value;
        
-       g_return_val_if_fail(dn != NULL, NULL);
+       cm_return_val_if_fail(dn != NULL, NULL);
        ou = attrkeyvalue_create();
        start = g_strstr_len(dn, strlen(dn), ",o=");
        if (start == NULL)
@@ -672,7 +592,7 @@ void ldapsvr_print_ldapmod(LDAPMod *mods[]) {
        gchar *mod_op;
        int i;
 
-       g_return_if_fail(mods != NULL);
+       cm_return_if_fail(mods != NULL);
        g_printerr( "Type\n");
        for (i = 0; NULL != mods[i]; i++) {
                LDAPMod *mod = (LDAPMod *) mods[i];
@@ -703,15 +623,35 @@ void ldapsvr_print_ldapmod(LDAPMod *mods[]) {
  */
 void ldapsvr_compare_attr(LDAP *ld, gchar *dn, gint cnt, LDAPMod *mods[]) {
        int i, rc;
-       
-       g_return_if_fail(ld != NULL || dn != NULL || cnt >= 0 || mods != NULL);
+
+#ifdef OPEN_LDAP_API_AT_LEAST_3000
+
+       struct berval val;
+
+#endif
+
+       cm_return_if_fail(ld != NULL || dn != NULL || cnt >= 0 || mods != NULL);
        for (i = 0; i < cnt; i++) {
                gchar *value = g_strdup(mods[i]->mod_vals.modv_strvals[0]);
                if (!value || strcmp(value, "") == 0)
                        value = g_strdup("thisisonlyadummy");
+
+#ifdef OPEN_LDAP_API_AT_LEAST_3000
+
+               val.bv_val = value;
+               val.bv_len = strlen(value);
+
+               rc = ldap_compare_ext_s(ld, dn, mods[i]->mod_type, &val, NULL, NULL);
+
+#else
+
+               /* This is deprecated as of OpenLDAP-2.3.0 */
                rc = ldap_compare_s(ld, dn, mods[i]->mod_type, value);
+
+#endif
+
                g_printerr("ldap_compare for (%s:%s)\" failed[0x%x]: %s\n",
-               mods[i]->mod_type, value, rc, ldap_err2string(rc));
+               mods[i]->mod_type, value, rc, ldaputil_get_error(ld));
                g_free(value);
        }
 }
@@ -737,7 +677,7 @@ int ldapsvr_compare_manual_attr(LDAP *ld, LdapServer *server, gchar *dn, char *a
        int retVal = -2, i;
        AttrKeyValue *mail;
 
-       g_return_val_if_fail(ld != NULL || server != NULL || attr != NULL, -1);
+       cm_return_val_if_fail(ld != NULL || server != NULL || attr != NULL, -1);
        ctl = server->control;
        mail = get_mail(dn);
        if (! mail)
@@ -745,9 +685,11 @@ int ldapsvr_compare_manual_attr(LDAP *ld, LdapServer *server, gchar *dn, char *a
        filter = g_strdup_printf("(&(mail=%s)(%s=*))", mail->value, attr);
        attrkeyvalue_free(mail);
        if (ctl) {
-               rc = ldap_search_s(ld, ctl->baseDN, /*LDAP_SCOPE_SUBTREE*/LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &res);
+
+               rc = ldap_search_ext_s(ld, ctl->baseDN, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, NULL, NULL, NULL, 0, &res);
+
                if (rc) {
-                       g_printerr("ldap_search for attr=%s\" failed[0x%x]: %s\n",attr, rc, ldap_err2string(rc));
+                       g_printerr("ldap_search for attr=%s\" failed[0x%x]: %s\n",attr, rc, ldaputil_get_error(ld));
                        retVal = -2;
                }
                else {
@@ -810,7 +752,13 @@ int ldapsvr_deside_operation(LDAP *ld, LdapServer *server, char *dn, char *attr,
        int rc;
        gboolean dummy = FALSE;
 
-       g_return_val_if_fail(ld != NULL || server != NULL || dn != NULL || attr != NULL, -1);
+#ifdef OPEN_LDAP_API_AT_LEAST_3000
+
+       struct berval val;
+
+#endif
+
+       cm_return_val_if_fail(ld != NULL || server != NULL || dn != NULL || attr != NULL, -1);
        if (value == NULL)
                return -1;
        /* value containing empty string cause invalid syntax. A bug in
@@ -820,9 +768,23 @@ int ldapsvr_deside_operation(LDAP *ld, LdapServer *server, char *dn, char *attr,
                value = g_strdup("thisisonlyadummy");
                dummy = TRUE;
        }
+
+#ifdef OPEN_LDAP_API_AT_LEAST_3000
+
+       val.bv_val = value;
+       val.bv_len = strlen(value);
+
+       rc = ldap_compare_ext_s(ld, dn, attr, &val, NULL, NULL);
+
+#else
+
+       /* This is deprecated as of OpenLDAP-2.3.0 */
        rc = ldap_compare_s(ld, dn, attr, value);
+
+#endif
+
        debug_print("ldap_compare for (%s:%s)\" error_code[0x%x]: %s\n",
-               attr, value, rc, ldap_err2string(rc));
+               attr, value, rc, ldaputil_get_error(ld));
        switch (rc) {
                case LDAP_COMPARE_FALSE: 
                        if (dummy)
@@ -876,7 +838,7 @@ void ldapsvr_handle_other_attributes(LDAP *ld, LdapServer *server, char *dn, GHa
        char *attr[ATTRIBUTE_SIZE + 1][2];
        int mod_op, rc, i;
 
-       g_return_if_fail(server != NULL || dn != NULL || contact != NULL);
+       cm_return_if_fail(server != NULL || dn != NULL || contact != NULL);
        for (i = 0; i <= ATTRIBUTE_SIZE; i++) {
                CHECKED_ATTRIBUTE[i] = FALSE;
                attr[i][0] = attr[i][1] = NULL;
@@ -887,7 +849,8 @@ void ldapsvr_handle_other_attributes(LDAP *ld, LdapServer *server, char *dn, GHa
                if (item) {
                        int index = get_attribute_index(item->key);
                        if (index >= 0) {
-                               debug_print("Found other attribute: %s = %s\n", item->key, item->value);
+                               debug_print("Found other attribute: %s = %s\n",
+                                               item->key?item->key:"null", item->value?item->value:"null");
                                mod_op = ldapsvr_deside_operation(ld, server, dn, item->key, item->value);
                                /* Only consider attributes which we no how to handle.
                                 * Set to TRUE in CHECKED_ATTRIBUTE array to indicate no further action
@@ -930,7 +893,7 @@ void ldapsvr_handle_other_attributes(LDAP *ld, LdapServer *server, char *dn, GHa
                }
                node = g_list_next(node);
        }
-       char **attribs = ldapctl_attribute_array(server->control);
+       char **attribs = ldapctl_full_attribute_array(server->control);
        for (i = 0; i < ATTRIBUTE_SIZE; i++) {
                /* Attributes which holds no information are to be removed */
                if (CHECKED_ATTRIBUTE[i] == FALSE) {
@@ -938,6 +901,10 @@ void ldapsvr_handle_other_attributes(LDAP *ld, LdapServer *server, char *dn, GHa
                         * If attributes are not part of the search criteria they would seem to hold
                         * no information since their values will not be populated in the GUI
                         */
+                       if (!strcmp(ATTRIBUTE[i], "jpegPhoto")) {
+                               debug_print("not updating jpegPhoto\n");
+                               continue;
+                       }
                        if (ldapsvr_check_search_attributes(attribs, (char *) ATTRIBUTE[i])) {
                                mod_op = ldapsvr_deside_operation(ld, server, dn, (char *) ATTRIBUTE[i], "");
                                if (mod_op == LDAP_MOD_DELETE) {
@@ -959,7 +926,7 @@ void ldapsvr_handle_other_attributes(LDAP *ld, LdapServer *server, char *dn, GHa
                                server->retVal = LDAPRC_ALREADY_EXIST;
                                break;
                        default:
-                               g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n",dn, rc, ldap_err2string(rc));
+                               g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n", dn, rc, ldaputil_get_error(ld));
                                if (rc == 0x8)
                                        server->retVal = LDAPRC_STRONG_AUTH;
                                else
@@ -967,12 +934,12 @@ void ldapsvr_handle_other_attributes(LDAP *ld, LdapServer *server, char *dn, GHa
                }
        }
        else {
-               /* Only consider those attributes which is currently part of the search criteria.
-                * If attributes are not part of the search criteria they would seem to hold
-                * no information since their values will not be populated in the GUI
-                */
-               char **attribs = ldapctl_attribute_array(server->control);
+               char **attribs = ldapctl_full_attribute_array(server->control);
                for (i = 0; i < ATTRIBUTE_SIZE; i++) {
+                       if (!strcmp(ATTRIBUTE[i], "jpegPhoto")) {
+                               debug_print("not updating jpegPhoto\n");
+                               continue;
+                       }
                        if (ldapsvr_check_search_attributes(attribs, (char *) ATTRIBUTE[i])) {
                                if (CHECKED_ATTRIBUTE[i] == FALSE) {
                                        AddrItemObject *aio = addrcache_get_object(server->addressCache, g_hash_table_lookup(contact , "uid"));
@@ -1011,7 +978,7 @@ void ldapsvr_add_contact(LdapServer *server, GHashTable *contact) {
        gchar *base_dn;
        GList *mailList;
 
-       g_return_if_fail(server != NULL || contact != NULL);
+       cm_return_if_fail(server != NULL || contact != NULL);
        node = g_hash_table_lookup(contact , "mail");
        if (node) {
                EmailKeyValue *newEmail = node->data;
@@ -1022,7 +989,8 @@ void ldapsvr_add_contact(LdapServer *server, GHashTable *contact) {
                clean_up(ld, server, contact);
                return;
        }
-       base_dn = g_strdup_printf("mail=%s,%s", email, server->control->baseDN);
+       base_dn = g_strdup_printf("mail=%s,%s",
+                       email, server->control->baseDN?server->control->baseDN:"null");
        g_free(email);
        person = 
                ldapsvr_get_contact(server, g_hash_table_lookup(contact , "uid"));
@@ -1100,7 +1068,8 @@ void ldapsvr_add_contact(LdapServer *server, GHashTable *contact) {
                                server->retVal = LDAPRC_ALREADY_EXIST;
                                break;
                        default:
-                               g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n",base_dn, rc, ldap_err2string(rc));
+                               g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n",
+                                               base_dn, rc, ldaputil_get_error(ld));
                                if (rc == 0x8)
                                        server->retVal = LDAPRC_STRONG_AUTH;
                                else
@@ -1132,13 +1101,14 @@ void ldapsvr_update_contact(LdapServer *server, GHashTable *contact) {
        GList *mailList;
        int mod_op;
 
-       g_return_if_fail(server != NULL || contact != NULL);
+       cm_return_if_fail(server != NULL || contact != NULL);
        ld = ldapsvr_connect(server->control);
        if (ld == NULL) {
                clean_up(ld, server, contact);
                return;
        }
        dn = g_hash_table_lookup(contact, "dn");
+
        if (dn == NULL) {
                clean_up(ld, server, contact);
                return;
@@ -1147,7 +1117,18 @@ void ldapsvr_update_contact(LdapServer *server, GHashTable *contact) {
        if (NoRemove) {
                /* We are trying to change RDN */
                gchar *newRdn = g_strdup_printf("%s=%s", NoRemove->attribute, NoRemove->value);
+
+#ifdef OPEN_LDAP_API_AT_LEAST_3000
+
+               int rc = ldap_rename_s(ld, dn, newRdn, NULL, 1, NULL, NULL);
+
+#else
+
+               /* This is deprecated as of OpenLDAP-2.3.0 */
                int rc = ldap_modrdn2_s(ld, dn, newRdn, 1);
+
+#endif
+
                if(rc != LDAP_SUCCESS) {
                        if (rc ==  LDAP_ALREADY_EXISTS) {
                                /* We are messing with a contact with more than one listed email
@@ -1161,15 +1142,21 @@ void ldapsvr_update_contact(LdapServer *server, GHashTable *contact) {
                        else {
                                g_printerr("Current dn: %s\n", dn);
                                g_printerr("new dn: %s\n", newRdn);
-                               g_printerr("LDAP Error(ldap_modrdn2_s) failed[0x%x]: %s\n", rc, ldap_err2string(rc));
+                               g_printerr("LDAP Error(ldap_modrdn2_s) failed[0x%x]: %s\n", rc, ldaputil_get_error(ld));
                                g_free(newRdn);
                                clean_up(ld, server, contact);
                                return;
                        }
                }
                else {
+                       ItemPerson *person = g_hash_table_lookup(contact, "person");
                        g_free(newRdn);
                        dn = g_strdup(NoRemove->new_dn);
+                       g_hash_table_replace(contact, "dn", dn);
+                       if (person) {
+                               g_free(person->externalID);
+                               person->externalID = dn;
+                       }
                }
        }
        else {
@@ -1311,7 +1298,7 @@ void ldapsvr_update_contact(LdapServer *server, GHashTable *contact) {
                rc = ldap_modify_ext_s(ld, dn, mods, NULL, NULL);
                if (rc) {
                        g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n",
-                    dn, rc, ldap_err2string(rc));
+                    dn, rc, ldaputil_get_error(ld));
                        server->retVal = LDAPRC_NAMING_VIOLATION;
                }
                if (mail)
@@ -1337,7 +1324,7 @@ void ldapsvr_delete_contact(LdapServer *server, GHashTable *contact) {
        gchar *dn;
        int rc;
 
-       g_return_if_fail(server != NULL || contact != NULL);
+       cm_return_if_fail(server != NULL || contact != NULL);
        ld = ldapsvr_connect(server->control);
        if (ld == NULL) {
                clean_up(ld, server, contact);
@@ -1352,7 +1339,7 @@ void ldapsvr_delete_contact(LdapServer *server, GHashTable *contact) {
        rc = ldap_delete_ext_s(ld, dn, NULL, NULL);
        if (rc) {
                g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n",
-                               dn, rc, ldap_err2string(rc));
+                               dn, rc, ldaputil_get_error(ld));
                server->retVal = LDAPRC_NODN;
        }
        clean_up(ld, server, contact);
@@ -1369,7 +1356,7 @@ void ldapsvr_update_book(LdapServer *server, ItemPerson *item) {
        GHashTable *contact = NULL;
        GList *contacts = NULL, *head = NULL;
 
-       g_return_if_fail(server != NULL);
+       cm_return_if_fail(server != NULL);
        debug_print("updating ldap addressbook\n");
 
        contact = g_hash_table_new(g_str_hash, g_str_equal);
@@ -1450,7 +1437,7 @@ void ldapsvr_update_book(LdapServer *server, ItemPerson *item) {
                        ldapsvr_delete_contact(server, contact);
                }
                else
-                       g_critical(_("ldapsvr_update_book->Unknown status: %s\n"), status);
+                       g_critical("ldapsvr_update_book->Unknown status: %s\n", status);
                contacts = g_list_next(contacts);
        }
        ldapsvr_free_hashtable(head);