static int domodrdn( LDAP *ld, char *dn, char *rdn, char *newsuperior, int remove_oldrdn ) { int rc = LDAP_SUCCESS; if ( ldaptool_verbose ) printf( gettext("new RDN: %1$s (%2$skeep existing values)\n"), rdn, remove_oldrdn ? "do not " : "" ); printf( gettext("%1$srenaming entry %2$s\n"), ldaptool_not ? "!" : "", dn ); if ( !ldaptool_not ) { rc = ldap_rename_s( ld, dn, rdn, newsuperior, remove_oldrdn, NULL, NULL ); if ( rc != LDAP_SUCCESS ) fprintf(stderr, gettext("ldap_rename_s: %s\n"), ldap_err2string(rc)); else if ( ldaptool_verbose ) printf( gettext("rename completed\n") ); } putchar('\n'); return( rc ); }
/* ARGSUSED */ int _ns_ldap_rename_s(char *service, int flags, char *dn, char *newrdn, char *newparent, int deleteoldrdn, LDAPControl ** serverctrls, LDAPControl **clientctrls) { LDAP *ld = __s_api_getLDAPconn(flags); return (ldap_rename_s(ld, dn, newrdn, newparent, deleteoldrdn, serverctrls, clientctrls)); }
int ldap_rename2_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn, LDAP_CONST char *newSuperior, int deleteoldrdn ) { return ldap_rename_s( ld, dn, newrdn, newSuperior, deleteoldrdn, NULL, NULL ); }
/* move a user to another container sets userprincipalname based on the destination container return AD_SUCCESS on success */ int ad_move_user(char *current_dn, char *new_container) { LDAP *ds; int result; char **exdn; char **username, *domain, *upn; ds=ad_login(); if(!ds) return ad_error_code; username=ad_get_attribute(current_dn, "sAMAccountName");; if(username==NULL) { snprintf(ad_error_msg, MAX_ERR_LENGTH, "Error getting username for dn %s for ad_move_user\n", current_dn); ad_error_code=AD_INVALID_DN; return ad_error_code; } domain=dn2domain(new_container); upn=malloc(strlen(username[0])+strlen(domain)+2); sprintf(upn, "%s@%s", username[0], domain); free(domain); result=ad_mod_replace(current_dn, "userPrincipalName", upn); free(upn); if(!result) return ad_error_code; exdn=ldap_explode_dn(current_dn, 0); if(exdn==NULL) { snprintf(ad_error_msg, MAX_ERR_LENGTH, "Error exploding dn %s for ad_move_user\n", current_dn); ad_error_code=AD_INVALID_DN; return ad_error_code; } result=ldap_rename_s(ds, current_dn, exdn[0], new_container, 1, NULL, NULL); ldap_memfree(exdn); if(result!=LDAP_SUCCESS) { snprintf(ad_error_msg, MAX_ERR_LENGTH, "Error in ldap_rename_s for ad_move_user: %s\n", ldap_err2string(result)); ad_error_code=AD_LDAP_OPERATION_FAILURE; } else { ad_error_code=AD_SUCCESS; } return ad_error_code; }
int ldap_modrdn_s( LDAP *ld, LDAP_CONST char *dn, LDAP_CONST char *newrdn ) { return ldap_rename_s( ld, dn, newrdn, NULL, 1, NULL, NULL ); }
static void do_modrdn( char *uri, char *manager, struct berval *passwd, char *entry, int maxloop, int maxretries, int delay, int friendly, int chaserefs ) { LDAP *ld = NULL; int i, do_retry = maxretries; char *DNs[2]; char *rdns[2]; int rc = LDAP_SUCCESS; char *p1, *p2; int version = LDAP_VERSION3; DNs[0] = entry; DNs[1] = strdup( entry ); /* reverse the RDN, make new DN */ p1 = strchr( entry, '=' ) + 1; p2 = strchr( p1, ',' ); *p2 = '\0'; rdns[1] = strdup( entry ); *p2-- = ','; for (i = p1 - entry;p2 >= p1;) DNs[1][i++] = *p2--; DNs[1][i] = '\0'; rdns[0] = strdup( DNs[1] ); DNs[1][i] = ','; i = 0; retry:; ldap_initialize( &ld, uri ); if ( ld == NULL ) { tester_perror( "ldap_initialize", NULL ); exit( EXIT_FAILURE ); } (void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ); (void) ldap_set_option( ld, LDAP_OPT_REFERRALS, chaserefs ? LDAP_OPT_ON : LDAP_OPT_OFF ); if ( do_retry == maxretries ) { fprintf( stderr, "PID=%ld - Modrdn(%d): entry=\"%s\".\n", (long) pid, maxloop, entry ); } rc = ldap_sasl_bind_s( ld, manager, LDAP_SASL_SIMPLE, passwd, NULL, NULL, NULL ); if ( rc != LDAP_SUCCESS ) { tester_ldap_error( ld, "ldap_sasl_bind_s", NULL ); switch ( rc ) { case LDAP_BUSY: case LDAP_UNAVAILABLE: if ( do_retry > 0 ) { do_retry--; if ( delay > 0) { sleep( delay ); } goto retry; } /* fallthru */ default: break; } exit( EXIT_FAILURE ); } for ( ; i < maxloop; i++ ) { rc = ldap_rename_s( ld, DNs[0], rdns[0], NULL, 0, NULL, NULL ); if ( rc != LDAP_SUCCESS ) { tester_ldap_error( ld, "ldap_rename_s", NULL ); switch ( rc ) { case LDAP_NO_SUCH_OBJECT: /* NOTE: this likely means * the second modrdn failed * during the previous round... */ if ( !friendly ) { goto done; } break; case LDAP_BUSY: case LDAP_UNAVAILABLE: if ( do_retry > 0 ) { do_retry--; goto retry; } /* fall thru */ default: goto done; } } rc = ldap_rename_s( ld, DNs[1], rdns[1], NULL, 1, NULL, NULL ); if ( rc != LDAP_SUCCESS ) { tester_ldap_error( ld, "ldap_rename_s", NULL ); switch ( rc ) { case LDAP_NO_SUCH_OBJECT: /* NOTE: this likely means * the first modrdn failed * during the previous round... */ if ( !friendly ) { goto done; } break; case LDAP_BUSY: case LDAP_UNAVAILABLE: if ( do_retry > 0 ) { do_retry--; goto retry; } /* fall thru */ default: goto done; } } } done:; fprintf( stderr, " PID=%ld - Modrdn done (%d).\n", (long) pid, rc ); ldap_unbind_ext( ld, NULL, NULL ); }
static PyObject * LDAPEntry_rename(LDAPEntry *self, PyObject *args, PyObject *kwds) { int rc; char *newparent_str, *newrdn_str, *olddn_str; PyObject *newdn, *newparent, *newrdn; PyObject *tmp; char *kwlist[] = {"newdn", NULL}; /* Client must be set. */ if (self->client == NULL) { PyErr_SetString(PyExc_AttributeError, "LDAPClient is not set."); return NULL; } /* Client must be connected. */ if (!self->client->connected) { PyObject *ldaperror = get_error("NotConnected"); PyErr_SetString(ldaperror, "Client has to connect to the server first."); Py_DECREF(ldaperror); return NULL; } if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &newdn)) { PyErr_SetString(PyExc_AttributeError, "Wrong parameter."); return NULL; } /* Save old dn string. */ tmp = PyObject_Str(self->dn); olddn_str = PyObject2char(tmp); Py_DECREF(tmp); if (olddn_str == NULL) return NULL; /* Validate and set new LDAP DN. */ if (LDAPEntry_setDN(self, newdn, NULL) != 0) return NULL; /* Get rdn and parent strings. */ newrdn = PyObject_CallMethod(self->dn, "get_rdn", "(i)", 0); newparent = PyObject_CallMethod(self->dn, "get_ancestors", NULL); if (newrdn == NULL || newparent == NULL) return NULL; newrdn_str = PyObject2char(newrdn); newparent_str = PyObject2char(newparent); Py_DECREF(newrdn); Py_DECREF(newparent); rc = ldap_rename_s(self->client->ld, olddn_str, newrdn_str, newparent_str, 1, NULL, NULL); if (rc != LDAP_SUCCESS) { //TODO Proper errors PyObject *ldaperror = get_error("LDAPError"); PyErr_SetString(ldaperror, ldap_err2string(rc)); Py_DECREF(ldaperror); free(olddn_str); free(newrdn_str); free(newparent_str); return NULL; } free(olddn_str); free(newrdn_str); free(newparent_str); return Py_None; }
/** * 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); }