/** * Delete contact from LDAP * * \param server AddressBook resource * \param contact GHashTable with object to delete */ void ldapsvr_delete_contact(LdapServer *server, GHashTable *contact) { LDAP *ld = NULL; gchar *dn; int rc; 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; } server->retVal = LDAPRC_SUCCESS; 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, ldaputil_get_error(ld)); server->retVal = LDAPRC_NODN; } clean_up(ld, server, contact); }
/** * Connect to LDAP server. * \param qry Query object to process. * \return Error/status code. */ static gint ldapqry_connect( LdapQuery *qry ) { LdapControl *ctl; LDAP *ld = NULL; /* Initialize connection */ if (debug_get_mode()) { debug_print("===ldapqry_connect===\n"); /*ldapqry_print(qry, stdout);*/ } ctl = qry->control; /*if (debug_get_mode()) { ldapctl_print(ctl, stdout); debug_print("======\n"); }*/ ldapqry_touch( qry ); qry->startTime = qry->touchTime; qry->elapsedTime = -1; ADDRQUERY_RETVAL(qry) = LDAPRC_INIT; ld = ldapsvr_connect(ctl); if (ld == NULL) return ADDRQUERY_RETVAL(qry); qry->ldap = ld; ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG; if( ldapqry_get_stop_flag( qry ) ) { return ADDRQUERY_RETVAL(qry); } ldapqry_touch( qry ); debug_print("connected to LDAP host %s on port %d\n", ctl->hostName?ctl->hostName:"null", ctl->port); ADDRQUERY_RETVAL(qry) = LDAPRC_STOP_FLAG; if( ldapqry_get_stop_flag( qry ) ) { return ADDRQUERY_RETVAL(qry); } ldapqry_touch( qry ); ADDRQUERY_RETVAL(qry) = LDAP_SUCCESS; return ADDRQUERY_RETVAL(qry); }
/** * Add new contact to LDAP * * \param server AddressBook resource * \param contact GHashTable with object to add */ void ldapsvr_add_contact(LdapServer *server, GHashTable *contact) { gchar *email = NULL, *param = NULL; LDAP *ld = NULL; LDAPMod *mods[MODSIZE]; LDAPMod modarr[7]; gint cnt = 0; char *cn[] = {NULL, NULL}; char *displayName[] = {NULL, NULL}; char *givenName[] = {NULL, NULL}; char **mail = NULL; char *sn[] = {NULL, NULL}; char *org[] = {NULL, NULL}; char *obj[] = {/*"top",*/ "person", "organizationalPerson", "inetOrgPerson", NULL}; int rc=0; GList *node; AttrKeyValue *ou, *commonName; ItemPerson *person; gchar *base_dn; GList *mailList; cm_return_if_fail(server != NULL || contact != NULL); node = g_hash_table_lookup(contact , "mail"); if (node) { EmailKeyValue *newEmail = node->data; email = g_strdup(newEmail->mail); } if (email == NULL) { server->retVal = LDAPRC_NODN; clean_up(ld, server, contact); return; } 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")); person->externalID = g_strdup(base_dn); debug_print("dn: %s\n", base_dn); ld = ldapsvr_connect(server->control); if (ld == NULL) { clean_up(ld, server, contact); debug_print("no ldap found\n"); return; } SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "objectClass", obj); cnt++; ou = get_ou(base_dn); if (ou != NULL) { SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, g_strdup(ou->key), org, g_strdup(ou->value)); cnt++; attrkeyvalue_free(ou); } commonName = get_cn(base_dn); if (commonName == NULL) { param = g_hash_table_lookup(contact , "cn"); if (param) { SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "cn", cn, param); } else { clean_up(ld, server, contact); debug_print("no CN found\n"); return; } } else { SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, g_strdup(commonName->key), cn, g_strdup(commonName->value)); cnt++; param = g_hash_table_lookup(contact , "cn"); SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "displayName", displayName, param); g_hash_table_insert(contact, "displayName", param); attrkeyvalue_free(commonName); } cnt++; param = g_hash_table_lookup(contact , "givenName"); if (param) { SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "givenName", givenName, param); cnt++; } mailList = g_hash_table_lookup(contact , "mail"); if (mailList) { char **tmp; tmp = g_malloc(sizeof(*tmp) * (g_list_length(mailList)+1)); mail = tmp; while (mailList) { EmailKeyValue *item = mailList->data; *tmp++ = g_strdup((gchar *) item->mail); mailList = g_list_next(mailList); } *tmp = NULL; SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "mail", mail); cnt++; } param = g_hash_table_lookup(contact, "sn"); if (param == NULL) param = g_strdup(N_("Some SN")); SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "sn", sn, param); cnt++; mods[cnt] = NULL; if (debug_get_mode()) { ldapsvr_print_ldapmod(mods); } server->retVal = LDAPRC_SUCCESS; rc = ldap_add_ext_s(ld, base_dn, mods, NULL, NULL); if (rc) { switch (rc) { case LDAP_ALREADY_EXISTS: server->retVal = LDAPRC_ALREADY_EXIST; break; default: 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 server->retVal = LDAPRC_NAMING_VIOLATION; } } ldapsvr_handle_other_attributes(ld, server, base_dn, contact); g_free(base_dn); clean_up(ld, server, contact); }
/** * Update contact to LDAP * * \param server AddressBook resource * \param contact GHashTable with object to update */ void ldapsvr_update_contact(LdapServer *server, GHashTable *contact) { LDAP *ld = NULL; LDAPMod *mods[MODSIZE]; LDAPMod modarr[4]; gint cnt = 0; gchar *param, *dn; Rdn *NoRemove = NULL; char *cn[] = {NULL, NULL}; char *givenName[] = {NULL, NULL}; char **mail = NULL; char *sn[] = {NULL, NULL}; GList *mailList; int mod_op; 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; } NoRemove = ldapsvr_modify_dn(contact, dn); 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 * address and the email we are changing is not the one used for dn */ /* It needs to be able to handle renaming errors to an already defined * dn. For now we just refuse the update. It will be caught later on as * a LDAPRC_NAMING_VIOLATION error. */ } 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, 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 { server->retVal = LDAPRC_NODN; clean_up(ld, server, contact); return; } param = g_hash_table_lookup(contact , "cn"); mod_op = ldapsvr_deside_operation(ld, server, dn, "displayName", param); if (mod_op >= 0 && (strcmp(param, NoRemove->value) != 0 && strcmp("cn", NoRemove->attribute) != 0)) { if (mod_op == LDAP_MOD_DELETE) { /* Setting param to NULL instructs OpenLDAP to remove any * value stored for this attribute and remove the attribute * completely. Should multiple instances of an attribute be * allowed in the future param is required to have the value * store for the attribute which is going to be deleted */ param = NULL; } if (mod_op == LDAP_MOD_REPLACE && strcmp(param, "") == 0) { /* Having an empty string is considered a syntax error in * ldap. E.g attributes with empty strings are not allowed * in which case we treate this as a request for deleting * the attribute. */ mod_op = LDAP_MOD_DELETE; param = NULL; } if (mod_op == LDAP_MOD_ADD && strcmp(param, "") == 0) { /* Adding an empty string is considered a syntax error in * ldap. E.g attributes with empty strings are not allowed * in which case we silently refuse to add this entry */ } else { SETMOD(mods[cnt], modarr[cnt], mod_op, "displayName", cn, param); cnt++; g_hash_table_insert(contact, "displayName", param); } } param = g_hash_table_lookup(contact , "givenName"); mod_op = ldapsvr_deside_operation(ld, server, dn, "givenName", param); if (mod_op >= 0 && (strcmp(param, NoRemove->value) != 0 && strcmp("givenName", NoRemove->attribute) != 0)) { if (mod_op == LDAP_MOD_DELETE) { /* Setting param to NULL instructs OpenLDAP to remove any * value stored for this attribute and remove the attribute * completely. Should multiple instances of an attribute be * allowed in the future param is required to have the value * store for the attribute which is going to be deleted */ param = NULL; } if (mod_op == LDAP_MOD_REPLACE && strcmp(param, "") == 0) { /* Having an empty string is considered a syntax error in * ldap. E.g attributes with empty strings are not allowed * in which case we treate this as a request for deleting * the attribute. */ mod_op = LDAP_MOD_DELETE; param = NULL; } if (mod_op == LDAP_MOD_ADD && strcmp(param, "") == 0) { /* Adding an empty string is considered a syntax error in * ldap. E.g attributes with empty strings are not allowed * in which case we silently refuse to add this entry */ } else { SETMOD(mods[cnt], modarr[cnt], mod_op, "givenName", givenName, param); cnt++; } } mailList = g_hash_table_lookup(contact , "mail"); if (mailList) { debug_print("# of mail: %d\n", g_list_length(mailList)); if (!(strcmp("mail", NoRemove->attribute) == 0 && g_list_length(mailList) == 1)) { char **tmp; tmp = g_malloc(sizeof(*tmp) * (g_list_length(mailList)+1)); mail = tmp; while (mailList) { EmailKeyValue *item = mailList->data; *tmp++ = g_strdup((gchar *) item->mail); mailList = g_list_next(mailList); } *tmp = NULL; /* * At least one email address is required * in which case it will always be a replace */ SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_REPLACE, "mail", mail); cnt++; } } else { /* * an error condition since at least one email adress * is required. Should never occur though. */ } param = g_hash_table_lookup(contact , "sn"); mod_op = ldapsvr_deside_operation(ld, server, dn, "sn", param); if (mod_op >= 0 && (strcmp(param, NoRemove->value) != 0 && strcmp("sn", NoRemove->attribute) != 0)) { if (mod_op == LDAP_MOD_DELETE) { /* Setting param to NULL instructs OpenLDAP to remove any * value stored for this attribute and remove the attribute * completely. Should multiple instances of an attribute be * allowed in the future param is required to have the value * store for the attribute which is going to be deleted */ param = NULL; } if (mod_op == LDAP_MOD_REPLACE && strcmp(param, "") == 0) { /* Having an empty string is considered a syntax error in * ldap. E.g attributes with empty strings are not allowed * in which case we treate this as a request for deleting * the attribute. */ mod_op = LDAP_MOD_DELETE; param = NULL; } if (mod_op == LDAP_MOD_ADD && strcmp(param, "") == 0) { /* Adding an empty string is considered a syntax error in * ldap. E.g attributes with empty strings are not allowed * in which case we silently refuse to add this entry */ } else { SETMOD(mods[cnt], modarr[cnt], mod_op, "sn", sn, param); cnt++; } } debug_print("newDN: %s\n", dn); if (NoRemove) rdn_free(NoRemove); server->retVal = LDAPRC_SUCCESS; if (cnt > 0) { int rc; mods[cnt] = NULL; 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, ldaputil_get_error(ld)); server->retVal = LDAPRC_NAMING_VIOLATION; } if (mail) g_free(mail); } ldapsvr_handle_other_attributes(ld, server, dn, contact); /* If we do not make changes persistent at this point then changes * will be lost if the user makes new search on the same server since * changes are only present in Claws' internal cache. This issue has to * be solved in addressbook.c since this involves access to structures * which are only accessible in addressbook.c */ clean_up(ld, server, contact); }