Author |
Topic: LDAP ModifyRDN Operation |
|
eLDAP member offline |
|
posts: |
107 |
joined: |
08/02/2006 |
from: |
Austin, TX |
|
|
|
|
|
LDAP ModifyRDN Operation |
While ModifyRDN refering to LDAP V2, ModifyDn refers to LDAP V3. Here is an excertp from RFC 2251:
4.9. Modify DN Operation
The Modify DN Operation allows a client to change the leftmost (least
significant) component of the name of an entry in the directory, or
to move a subtree of entries to a new location in the directory. The
Modify DN Request is defined as follows:
ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
entry LDAPDN,
newrdn RelativeLDAPDN,
deleteoldrdn BOOLEAN,
newSuperior [0] LDAPDN OPTIONAL }
Parameters of the Modify DN Request are:
- entry: the Distinguished Name of the entry to be changed. This
entry may or may not have subordinate entries.
- newrdn: the RDN that will form the leftmost component of the new
name of the entry.
- deleteoldrdn: a boolean parameter that controls whether the old RDN
attribute values are to be retained as attributes of the entry, or
deleted from the entry.
- newSuperior: if present, this is the Distinguished Name of the entry
which becomes the immediate superior of the existing entry.
The result of the name change attempted by the server upon receipt of
a Modify DN Request is returned in the Modify DN Response, defined
as follows:
ModifyDNResponse ::= [APPLICATION 13] LDAPResult
Upon receipt of a ModifyDNRequest, a server will attempt to
perform the name change. The result of the name change attempt will
be returned to the client in the Modify DN Response.
For example, if the entry named in the "entry" parameter was
"cn=John Smith,c=US", the newrdn parameter was "cn=John Cougar Smith",
and the newSuperior parameter was absent, then this operation would
attempt to rename the entry to be "cn=John Cougar Smith,c=US". If
there was already an entry with that name, the operation would fail
with error code entryAlreadyExists.
If the deleteoldrdn parameter is TRUE, the values forming the old
RDN are deleted from the entry. If the deleteoldrdn parameter is
FALSE, the values forming the old RDN will be retained as
non-distinguished attribute values of the entry. The server may
not perform the operation and return an error code if the setting of
the deleteoldrdn parameter would cause a schema inconsistency in the
entry.
Note that X.500 restricts the ModifyDN operation to only affect
entries that are contained within a single server. If the LDAP
server is mapped onto DAP, then this restriction will apply, and the
resultCode affectsMultipleDSAs will be returned if this error
occurred. In general clients MUST NOT expect to be able to perform
arbitrary movements of entries and subtrees between servers.
|
|
|
|
|
|
|
eLDAP member offline |
|
posts: |
107 |
joined: |
08/02/2006 |
from: |
Austin, TX |
|
|
|
|
|
A JNDI CLient |
Here is a programming example to show how to change the leftmost component of the name of an entry in the directory, or to move a subtree to a new location in the directory.
/**
*
* ModifyRDN .java
* Sample code to demostrate how ModifyRDN/ModifyDN works.
*
*/
import javax.naming.*;
import javax.naming.directory.*;
import java.util.Hashtable;
public class ModifyRDN
{
public static void main(String[] args)
{
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://myLdapServer:389/dc=myDomain,dc=com");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=directory manager");
env.put(Context.SECURITY_CREDENTIALS, "password");
/*
Whether the old RDN attribute values are to be retained
as attributes of the entry, or deleted from the entry
*/
env.put("java.naming.ldap.deleteRDN", "true"); // default is 'true'
try {
/* Create the initial context */
DirContext ctx = new InitialDirContext(env);
ctx.rename("cn=John Smith,ou=Sales,ou=People",
"cn=John Cougar Smith,ou=Sales,ou=People");
/* Close the context when it's done */
ctx.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
|
|
|
|
|
|
|
eLDAP member offline |
|
posts: |
107 |
joined: |
08/02/2006 |
from: |
Austin, TX |
|
|
|
|
|
Error 1 -- AD doesn't support 'deleteoldrdn' |
The above example works fine for both AD and SunOne. When 'deleteoldrdn' is set as 'false':
env.put("java.naming.ldap.deleteRDN", "false"); which means the old rdn is intended to be kept somewhere as attribute in the new entry, it works only for SunOne. For AD, you will get error messages like the following:
javax.naming.OperationNotSupportedException: [LDAP: error code 53 - 00000057: LdapErr: DSID-0C0909A4, comment: Old RDN must be deleted, data 0, vece] remaining name 'cn=John Smith,ou=Sales,ou=People' at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:2728) at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2601) at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2411) at com.sun.jndi.ldap.LdapCtx.c_rename(LdapCtx.java:584) at com.sun.jndi.toolkit.ctx.ComponentContext.p_rename(ComponentContext.java:692) at com.sun.jndi.toolkit.ctx.PartialCompositeContext.rename(PartialCompositeContext.java:248) at com.sun.jndi.toolkit.ctx.PartialCompositeContext.rename(PartialCompositeContext.java:239) at javax.naming.InitialContext.rename(InitialContext.java:382)
|
|
|
|
|
|
|
eLDAP member offline |
|
posts: |
107 |
joined: |
08/02/2006 |
from: |
Austin, TX |
|
|
|
|
|
Error 2 -- entryAlreadyExists |
If there was already an entry with that name, the operation would fail with error code entryAlreadyExists.
Error messages from AD: javax.naming.NameAlreadyBoundException: [LDAP: error code 68 - 00002071: UpdErr: DSID-031B0B59, problem 6005 (ENTRY_EXISTS), data 0]; remaining name 'cn=John Cougar Smith,ou=Sales,ou=People' at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:2647) at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2601) at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2411) at com.sun.jndi.ldap.LdapCtx.c_rename(LdapCtx.java:584) at com.sun.jndi.toolkit.ctx.ComponentContext.p_rename(ComponentContext.java:692) at com.sun.jndi.toolkit.ctx.PartialCompositeContext.rename(PartialCompositeContext.java:248) at com.sun.jndi.toolkit.ctx.PartialCompositeContext.rename(PartialCompositeContext.java:239) at javax.naming.InitialContext.rename(InitialContext.java:382)
Error messages from SunOne:: javax.naming.NameAlreadyBoundException: [LDAP: error code 68 - Entry Already Exists]; remaining name 'cn=John Cougar Smith,ou=Sales,ou=People' at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:2647) at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2601) at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2411) at com.sun.jndi.ldap.LdapCtx.c_rename(LdapCtx.java:584) at com.sun.jndi.toolkit.ctx.ComponentContext.p_rename(ComponentContext.java:692) at com.sun.jndi.toolkit.ctx.PartialCompositeContext.rename(PartialCompositeContext.java:248) at com.sun.jndi.toolkit.ctx.PartialCompositeContext.rename(PartialCompositeContext.java:239) at javax.naming.InitialContext.rename(InitialContext.java:382)
|
|
|
|
|
|
|
eLDAP member offline |
|
posts: |
107 |
joined: |
08/02/2006 |
from: |
Austin, TX |
|
|
|
|
|
Error 3 -- Not Allowed On Non-leaf Node |
If we change the code to modify an non-leaf node, or an interior node, by:
ctx.rename("ou=Sales,ou=People",
"ou=International Sales,ou=People"); AD: (It works fine without error)
SunOne: javax.naming.ContextNotEmptyException: [LDAP: error code 66 - Not Allowed On Non-leaf]; remaining name 'ou=Sales,ou=Peoplee' at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:2690) at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2601) at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2411) at com.sun.jndi.ldap.LdapCtx.c_rename(LdapCtx.java:584) at com.sun.jndi.toolkit.ctx.ComponentContext.p_rename(ComponentContext.java:692) at com.sun.jndi.toolkit.ctx.PartialCompositeContext.rename(PartialCompositeContext.java:248) at com.sun.jndi.toolkit.ctx.PartialCompositeContext.rename(PartialCompositeContext.java:239) at javax.naming.InitialContext.rename(InitialContext.java:382)
|
|
|
|
|
|
|
eLDAP member offline |
|
posts: |
107 |
joined: |
08/02/2006 |
from: |
Austin, TX |
|
|
|
|
|
Error 4 -- not support moving of entries |
If we change the code to move an entry from one branch unto anther branch, by:
ctx.rename("cn=John Smith,ou=Sales,ou=People",
"cn=John Smith,ou=International Sales,ou=People"); AD: (It works fine without error)
SunOne: javax.naming.OperationNotSupportedException: [LDAP: error code 53 - server does not support moving of entries]; remaining name 'cn=John Smith,ou=Sales,ou=People' at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:2728) at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2601) at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2411) at com.sun.jndi.ldap.LdapCtx.c_rename(LdapCtx.java:584) at com.sun.jndi.toolkit.ctx.ComponentContext.p_rename(ComponentContext.java:692) at com.sun.jndi.toolkit.ctx.PartialCompositeContext.rename(PartialCompositeContext.java:248) at com.sun.jndi.toolkit.ctx.PartialCompositeContext.rename(PartialCompositeContext.java:239) at javax.naming.InitialContext.rename(InitialContext.java:382)
|
|
|
|
|
|
|
eLDAP member offline |
|
posts: |
107 |
joined: |
08/02/2006 |
from: |
Austin, TX |
|
|
|
|
|
Observations |
Based on the above runs, it seems that:
SunOne behaves like an LDAPv2 server which supports ModifyRDN AD (Active Directory) functions as an LDAPv3 server which supports ModifyRDN and ModifyDN.
|
|
|
|
|
|
|
eLDAP member offline |
|
posts: |
107 |
joined: |
08/02/2006 |
from: |
Austin, TX |
|
|
|
|
|
Line Command of LDAP ModiyRDN |
The above testing runs can also be done by SunOne Directory line command ldapmodify.exe in conjunction with the corresponding LDIF (RFC 2849):
# Modify an entry's relative distinguished name
dn: cn=Paul Jensen, ou=Product Development, dc=airius, dc=com
changetype: modrdn
newrdn: cn=Paula Jensen
deleteoldrdn: 1
# Rename an entry and move all of its children to a new location in
# the directory tree (only implemented by LDAPv3 servers).
dn: ou=PD Accountants, ou=Product Development, dc=airius, dc=com
changetype: modrdn
newrdn: ou=Product Development Accountants
deleteoldrdn: 0
newsuperior: ou=Accounting, dc=airius, dc=com
|
|
|
|
|
|
|
eLDAP member offline |
|
posts: |
107 |
joined: |
08/02/2006 |
from: |
Austin, TX |
|
|
|
|
|
Changelog format of LDAP ModifyRDN |
In some case a changelog is required for replication purpose. Here is the format sepcified in SPEC: draft-good-ldap-changelog-04.txt
changeNumber: the change number, as assigned by the supplier. This
integer MUST strictly increase as new entries are added, and must
always be unique within a given server.
Syntax: INTEGER
targetdn: the distinguished name of the entry which was added,
modified or deleted. In the case of a modrdn operation, the
targetdn gives the DN of the entry before it was modified.
Syntax: DN
changeType: the type of change. One of: "add", "delete", "modify",
"modrdn". Later RFCs may define additional values for changeType.
Syntax: DirectoryString
changes: the changes which were made to the directory server. These
changes are in LDIF format, which is described in [1].
Syntax: OctetString
newRDN: the new RDN (Relative Distinguished Name) of the entry, if
the changeType is "modrdn". If the changeType attribute does not
have the value "modrdn", then there should be no values contained in
the newRDN attribute.
Syntax: DN
deleteOldRDN: a flag which tells whether the old RDN of the entry
should be retained as a distinguished attribute of the entry, or
should be deleted. A value of "FALSE" indicates that the RDN should
be retained as a distinguished attribute, and a value of "TRUE"
indicates that it should not be retained as a distinguished
attribute of the entry. If any value other than "TRUE" or "FALSE"
is contained in the deleteOldRDN, the RDN should be retained as a
distinguished attribute (that is, "FALSE" is the default if no
values are present, or if illegal values are present).
Syntax: BOOLEAN
newSuperior: if present, gives the name of the entry which becomes
the immediate superior of the existing entry. This optional
attribute reflects LDAPv3 functionality, and MUST NOT be generated
by LDAPv2 servers [2].
Syntax: DN
Example:
A changeLogEntry representing a modrdn operation
performed on an entry in the directory
dn: changenumber=10042, cn=changelog
changenumber: 10042
targetdn: cn=Bjorn Jensen, ou=Product Development, o=Ace Industry,
c=US
changetype: modrdn
newrdn: cn=Bjorn J Jensen
deleteoldrdn: FALSE
|
|
|
|
|
|
|
|