Because LDIF can represent LDAP update operations, you can use LDIF to modify the schema.
To add a class, simply add an attribute value that conforms to the specification for NDSObjectClassDescription to the objectClasses attribute of the subschemaSubentry.
NDSObjectClassDescription = "(" whsp numericoid whsp [ "NAME" qdescrs ] [ "DESC" qdstring ] [ "OBSOLETE" whsp ] [ "SUP" oids ] [ ( "ABSTRACT" / "STRUCTURAL" / "AUXILIARY" ) whsp ] [ "MUST" oids ] [ "MAY" oids ] [ "X-NDS_NOT_CONTAINER" qdstrings ] [ "X-NDS_NONREMOVABLE" qdstrings ] [ "X-NDS_CONTAINMENT" qdstrings ] [ "X-NDS_NAMING" qdstrings ] [ "X-NDS_NAME" qdstrings ] whsp ")"
The following example LDIF file adds the person objectClass to the schema:
1 version: 1 2 dn: cn=schema 3 changetype: add 4 objectClasses: ( 2.5.6.6 NAME 'person' DESC 'Standard 5 ObjectClass' SUP ndsLoginProperties STRUCTURAL MUST 6 (cn $ sn) MAY (description $ seeAlso $ telephoneNum 7 ber $ fullName $ givenName $ initials $ uid $ userPa 8 ssword) X-NDS_NAMING ('cn' 'uid') X-NDS_CONTAINMENT 9 ('organization' 'organizationalUnit' 'domain') X-NDS 10 _NAME 'Person' X-NDS_NOT_CONTAINER '1' X-NDS_NONREMO 11 VABLE '1') 12
Mandatory attributes are listed in the MUST section of the object class description. For the person object class, the mandatory attributes are cn and sn.
Optional attributes are listed in the MAY section of the object class description. The optional attributes in the person object class are description, seeAlso, telephoneNumber, fullName, givenName, initials, uid, and userPassword.
NOTE:The userPassword attribute cannot be used as an optional (MAY) attribute. The operation will fail if you try to use it as a mandatory (MUST) attribute in the new objectClass using this LDIF format to extend the schema.
The object classes that can contain the object class being defined are given in the X-NDS_CONTAINMENT section of the object class description. The person object class can be contained by the organization, organizationalUnit, and domain object classes.
To add an attribute, simply add an attribute value that conforms to the specification for NDSAttributeTypeDescription to the attributes attribute of the subschemaSubentry.
NDSAttributeTypeDescription = "(" whsp numericoid whsp ; AttributeType identifier [ "NAME" qdescrs ] ; name used in AttributeType [ "DESC" qdstring ] ; description [ "OBSOLETE" whsp ] [ "SUP" woid ] ; derived from this other AttributeType [ "EQUALITY" woid] ; Matching Rule name [ "ORDERING" woid] ; Matching Rule name [ "SUBSTR" woid ] ; Matching Rule name [ "SYNTAX" whsp noidlen whsp ] ; Syntax OID [ "SINGLE-VALUE" whsp ] ; default multi-valued [ "COLLECTIVE" whsp ] ; default not collective [ "NO-USER-MODIFICATION" whsp ] ; default user modifiable [ "USAGE" whsp AttributeUsage ] ; default userApplications [ "X-NDS_PUBLIC_READ" qdstrings ] ; default not public read ('0') [ "X-NDS_SERVER_READ" qdstrings ] ; default not server read ('0') [ "X-NDS_NEVER_SYNC" qdstrings ] ; default not never sync ('0') [ "X-NDS_NOT_SCHED_SYNC_IMMEDIATE" qdstrings ] ; default sched sync immediate ('0') [ "X-NDS_SCHED_SYNC_NEVER" qdstrings ] ; default schedule sync ('0') [ "X-NDS_LOWER_BOUND" qdstrings ] ; default no lower bound('0') ;(upper is specified in SYNTAX) [ "X-NDS_NAME_VALUE_ACCESS" qdstrings ] ; default not name value access ('0') [ "X-NDS_NAME" qdstrings ] ; legacy NDS name whsp ")"
The following example LDIF file adds the title attribute type to the schema:
1 version: 1 2 dn: cn=schema 3 changetype: add 4 attributeTypes: ( 2.5.4.12 NAME 'title' DESC 'Standa 5 rd Attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{ 6 64} X-NDS_NAME 'Title' X-NDS_NOT_SCHED_SYNC_IMMEDIA 7 TE '1' X-NDS_LOWER_BOUND '1') 8
An attribute defaults to multivalued unless it is explicitly made single-valued. The following example LDIF file makes title single-valued by adding the SINGLE-VALUE keyword after the SYNTAX section:
1 version: 1 2 dn: cn=schema 3 changetype: add 4 attributeTypes: ( 2.5.4.12 NAME 'title' DESC 'Standa 5 rd Attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{ 6 64} SINGLE-VALUE X-NDS_NAME 'Title' X-NDS_NOT_SCHED 7 _SYNC_IMMEDIATE '1' X-NDS_LOWER_BOUND '1') 8
Although adding new schema elements is an acceptable practice, modifying or extending existing schema elements is usually dangerous. Because every schema element is uniquely identified by an OID, when you extend a standard schema element, you effectively create a second definition for the element even though it still uses the original OID. This can cause incompatibility problems.
There are times when it is appropriate to change schema elements. For example, you might need to extend or modify new schema elements as you refine them during development. Instead of adding new attributes directly to a class, you should generally use auxiliary classes only to
Add new attributes to an existing object class.
Subclass an existing object class.
The following sample LDIF file creates two new attributes, creates an auxiliary class with these new attributes, then adds an inetOrgPerson entry with the auxiliary class as an object class of the entry and with values for the auxiliary class attributes.
version: 1 # Add an attribute to track a bear's hair. The attribute is # multi-valued, uses a case ignore string syntax, # and has public read rights # Values may include: long hair, short, curly, straight, # none, black, and brown # X-NDS_PUBLIC_READ '1' The 1 allows public read, # 0 denies public read dn: cn=schema changetype: modify add: attributeTypes attributeTypes: ( 2.16.840.1.113719.1.186.4.10 NAME 'bearHair' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-NDS_PUBLIC_READ '1' ) # add an attribute to store a bear's picture dn: cn=schema changetype: modify add: attributeTypes attributeTypes: ( 2.16.840.1.113719.1.186.4.11 NAME 'bearPicture' SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 SINGLE-VALUE ) # create an Auxiliary class for the bearfeatures dn: cn=schema changetype: modify add: objectclasses objectclasses: (2.16.840.1.113719.1.186.6.101 NAME 'bearFeatures' MAY (bearHair $ bearPicture) AUXILIARY) # now create a user named bobby dn: cn=bobby,o=bearcave changetype: add cn: bobby sn: bear givenName: bobby bearHair: Short bearHair: Brown bearHair: Curly bearPicture:< file:///c:/tmp/alien.jpg objectClass: top objectClass: person objectClass: inetOrgPerson objectClass: bearFeatures # now create a person named john that will later be changed # into a bear when bearFeatures is added to its objectClass # list dn: cn=john,o=bearcave changetype: add cn: John sn: bear givenName: john objectClass: top objectClass: person objectClass: inetOrgPerson # now morph john into a bear by adding bearFeatures dn: cn=john,o=bearcave changetype: modify add: objectClass objectClass: bearFeatures - add: bearHair bearHair: long bearHair: black #bearPicture:< file:///c:/tmp/john.jpg> - # to morph john back to a person, simply delete the # objectClass bearFeatures dn: cn=john,o=bearcave changetype: modify delete: objectClass objectClass: bearFeatures
When removing auxiliary classes, you don't have to delete all of the values associated with the auxiliary class when you remove the auxiliary class from the objectClass list. eDirectory does this automatically.
If the auxiliary class had MUST attributes, they must all be specified in the same modify operation that adds the auxiliary class to the objectClass list, or the modification will fail.
XML processing of any LDIF Record (LDIF format or records generated from LDAP server) will not succeed if the individual records will not satisfy all the XML rules specified in the XML file.