Getting Started with OpenLDAP, Part 4

I hope readers have explored the various attributes used to create records in LDAP directories. Once you have a list of the data items (attributes) that you want to store in your directory, the next step is to locate the appropriate ObjectClasses that contain those attributes. You can use multiple ObjectClasses in one record, but not all ObjectClasses can be used together. In this article, we will discuss how to find and use ObjectClasses to obtain all the attributes needed to store the desired data in a directory.

Let us approach this exercise with a specific example—an addressbook, or in other words, a directory containing personal information about friends. The information we would normally want to store for each entry would be as follows:

  1. Name of the person
  2. Complete address, along with PIN code
  3. Home phone number
  4. Mobile phone number
  5. e-mail address

To create a directory with the above information, we would need to look at attributes that provide the above. Based on the attributes, we will determine the ObjectClasses to be used.

Let’s look into the OpenLDAP schema files to determine which ObjectClasses contain the corresponding attributes. Since the name of a person is designated as the ‘Common Name’ or the cn attribute, a search on an ObjectClass containing the cn attribute would be ideal. Let us search the core.schema file for such an ObjectClass:

[root@vbg schema]# cat /etc/openldap/schema/core.schema | egrep -A 5 ^objectclas | grep -B 3 cn | head -n 5
objectclass ( NAME 'person'
	DESC 'RFC2256: a person'
	MUST ( sn $ cn )

I have piped the output to the head command to show the first ObjectClass that contains the attribute cn. From the above output, it seems that we might use the ObjectClass person in our addressbook. Let’s see what other attributes this ObjectClass provides:

[root@vbg schema]# cat /etc/openldap/schema/core.schema | grep -A 5 "objectclass ( NAME 'person'"
objectclass ( NAME 'person'
	DESC 'RFC2256: a person'
	MUST ( sn $ cn )
	MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )

We find that the person ObjectClass has the attributes sn (surname), cn (common name), userPassword, telephoneNumber, seeAlso and description. From this, it’s clear that the person ObjectClass alone will not suffice for our addressbook, since it does not have attributes for the person’s address, mobile number and e-mail address.

Before continuing our search for other ObjectClasses that will provide us with the other required attributes, let’s take a look at the ObjectClass definition syntax. The exact formal syntax is defined in RFC 2252, but I present a simplified syntax below:

ojectclass ( NAME

             MUST ()
             MAY ())

Looking at the definition of the person ObjectClass, and matching it with the syntax definition provided above, we can interpret the person ObjectClass definition as follows:

  • OID (for person ObjectClass) is
  • NAME (for person objectclass) is person
  • Superior/parent ObjectClass for person ObjectClass is TOP
  • Type of person ObjcetClass is STRUCTURAL
  • Attributes that must be defined when using person ObjectClass are sn, cn
  • Attributes that can be defined when using person ObjectClass are userPassword, telephoneNumber, seeAlso and description

Types of ObjectClasses

There are three types of ObjectClasses: abstract, auxiliary and structural. A structural ObjectClass provides the underlying schema for a record; every entry/record in a directory needs to have a structural ObjectClass. You can use only one structural class in an entry, i.e., you cannot define an entry with two structural classes. There is an exception though: you can specify multiple structural classes that are part of the same ObjectClass hierarchy (the parent-child relationship).

ObjectClass, like attributes, as discussed in the previous article, have a hierarchical relationship. A child ObjectClass inherits the attributes of its parents. You don’t really need to specify a given structural ObjectClass in an entry if you specify one of its children; the attributes that you might want to use from the parent ObjectClass would already be available, having been inherited from the parent ObjectClass.

Given below is an example of an invalid entry:

objectclass: person
objectclass: organizationalRole

If you look into the core.schema file and check these ObjectClass definitions, you will see that both these ObjectClasses are structural, and both have top as their superior—they are not related to each other. An entry with the following ObjectClasses, though, is valid:

objectclass: person
objectclass: organizationalPerson

Although both these classes are structural, the definition for the organizationalPerson ObjectClass specifies that the person ObjectClass is its superior:

[root@vbg schema]# cat /etc/openldap/schema/core.schema | grep -A 2 "objectclass ( NAME organizationalPerson'"
objectclass ( NAME 'organizationalPerson'
	DESC 'RFC2256: an organizational person'

Auxiliary classes can be attached to any entry that has a structural class. They are used to provide extra attributes for an entry, without altering the basic structure of the entry. This is very useful in advanced LDAP usage. As an example, the ObjectClass pkiUser can be used to represent certificate objects:

[root@vbg schema]# cat /etc/openldap/schema/core.schema | grep -A 5 "objectclass ( NAME 'pkiUser'"
objectclass ( NAME 'pkiUser'
	DESC 'RFC2587: a PKI user'
	MAY userCertificate )

If we wanted to also store user certificate information in our address book, our entry could have used this auxiliary class along with a structural class, as shown below:

objectclass: person
objectclass: pkiUser

We could use the person structural ObjectClass along with the pkiUser ObjectClass in our entry as shown above.

Abstract ObjectClasses are used for convenience. The most common abstract ObjectClass is top, which is defined as the superior (SUP) for a lot of structural ObjectClasses. Any structural class that does not have another structural class as its parent (like the person ObjectClass) is defined with the abstract class top as its parent. Let’s take a quick look at the definition of this ObjectClass:

root@vbg schema]# cat /etc/openldap/schema/core.schema | grep -A 3 "objectclass ( NAME 'top'"
#objectclass ( NAME 'top'
##	DESC 'RFC2256: top of the superclass chain'
##	MUST objectClass )

The above definition states that whenever the top ObjectClass is used in an entry, other ObjectClasses must be specified, for it to be a valid entry.

Back to the search for addressbook attributes

Let’s look at the definition of the organizationalPerson ObjectClass:

root@vbg schema]# cat /etc/openldap/schema/core.schema | grep -A 7 "objectclass ( NAME 'organizationalPerson'"
objectclass ( NAME 'organizationalPerson'
	DESC 'RFC2256: an organizational person'
	MAY ( title $ x121Address $ registeredAddress $ destinationIndicator $
		preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
		telephoneNumber $ internationaliSDNNumber $
		facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
		postalAddress $ physicalDeliveryOfficeName $ ou $ st $ l ) )

If we used the organizationalPerson ObjectClass for our address book, the following attributes would be available to us:

  • cn, sn, userPassword, telephoneNumber, seeAlso, description (from the superior person ObjectClass; remember that cn and sn are mandatory)
  • title, x121Address, registeredAddress, etc (attributes of organizationalPerson)

That’s progress, but we still don’t have attributes for the e-mail address and mobile phone number that we want to store in our addressbook, so even the organizationalPerson ObjectClass is not sufficient for our needs. Let’s search our schema folder for an ObjectClass with a mail attribute:

[root@vbg schema]# grep -ri " $ mail" /etc/openldap/schema/
/etc/openldap/schema/inetorgperson.schema:		labeledURI $ mail $ manager $ mobile $ o $ pager $
/etc/openldap/schema/misc.schema:	MAY	( mailLocalAddress $ mailHost $ mailRoutingAddress ) )

You might have guessed why I used the $ sign while searching for the mail attribute within the entire schema directory for the file that contains it. As attributes are separated using the $ sign in an ObjectClass definition, the best way to find an ObjectClass with mail as an attribute would be to search for the pattern $ mail.

The grep output shows that the mail attribute is defined in some ObjectClasses in the inetorgperson.schema file, so let’s search that file for the ObjectClass:

[root@vbg schema]# cat /etc/openldap/schema/inetorgperson.schema | grep -B 9 -A 4 mail
objectclass	( 2.16.840.1.113730.3.2.2
    NAME 'inetOrgPerson'
	DESC 'RFC2798: Internet Organizational Person'
    SUP organizationalPerson
	MAY (
		audio $ businessCategory $ carLicense $ departmentNumber $
		displayName $ employeeNumber $ employeeType $ givenName $
		homePhone $ homePostalAddress $ initials $ jpegPhoto $
		labeledURI $ mail $ manager $ mobile $ o $ pager $
		photo $ roomNumber $ secretary $ uid $ userCertificate $
		x500uniqueIdentifier $ preferredLanguage $
		userSMIMECertificate $ userPKCS12 )

The mail attribute is included in the inetOrgPerson objectclass. The inetOrgPerson structural class, which is a child of the organizationalPerson class (and therefore grandchild of the person class), is also a structural ObjectClass. That means that this class has all the attributes we found useful in person and organizationalPerson, plus the mail and mobile attributes, which we were missing earlier. If we use this class for our addressbook data we can get the following attributes :

  • Name of the Person: Common Name (cn) from ObjectClass person
  • Address: Street (street) , locality name (l) , state (st) , PIN Code (postalCode) from ObjectClass organizationalPerson
  • Home Phone: Landline phone number (homePhone) from ObjectClass inetOrgPerson
  • Mobile Phone Number: mobile from ObjectClass inetOrgPerson
  • e-mail address: mail from objectclass inetOrgPerson

This fulfils all our requirements, but we also need to supply a value for the mandatory sn (surname) attribute of the person ObjectClass. A skeleton entry for our address book record would then be as follows:

objectclass: top
objectclass: inetOrgPerson

Now let us go back to the sample LDIF file, created by us in the first article of this series, for our address book directory:

[vbg@vbg-work openldap]$ cat /tmp/ldap.ldif
dn: dc=knafl,dc=org
dc: knafl
objectClass: top
objectClass: domain

dn: ou=addressbook,dc=knafl,dc=org
ou: addressbook
objectClass: top
objectClass: organizationalUnit

dn:cn=Varad Gupta,ou=addressbook,dc=knafl,dc=org
cn: Varad Gupta
sn: Gupta
l: Gurgaon
street: M-37, Old DLF Colony, Sector-14
st: Haryana
postalCode: 122003
homePhone: 0124 22222222
mobile: 0999999999
objectClass: top
objectClass: inetOrgPerson

You can look at the last entry and observe how data will be added to the addressbook. I leave it as an exercise for the reader to decipher the first two entries in the above LDIF file.

No Comments


  1. Getting Started with OpenLDAP, Part 5 | FOSTERing Linux - [...] In Part 4, we created an OpenLDAP-based address book with basic data. In this article, we will focus on …

Leave a Reply

Your email address will not be published. Required fields are marked *