LDIF syntax explanation
Suppose you use an LDIF file like this:
# Create the user group dn: cn=networkusers,ou=groups,dc=saruman,dc=biz objectClass: posixGroup gidNumber: 10001 cn: TestGroup description: Internal network users # Create a new user: dn: uid=sixpacjo,ou=people,dc=saruman,dc=biz objectClass: top objectClass: posixAccount objectClass: shadowAccount objectClass: inetOrgPerson cn: Joe Sixpack description: Your Average Network User givenName: Joe sn: Sixpack mail: joe.sixpack@saruman.biz mail: j.sixpack@saruman.biz # The Unix login-name for the user: uid: sixpacjo # The group and user IDs: gidNumber: 10001 uidNumber: 10001 # The Unix account data: homeDirectory: /home/sixpacjo loginShell: /bin/bash # The encrypted password for the user: userPassword: {crypt}$1$qs70ynbk$UBuewN7ZdIvqavIxkxdmX0
What are you then actually doing? Well, you're adding two objects; the different attributes in this LDIF file are explained below. Note that this is not an exhaustive explanation of the syntax, just a quick primer for those too busy to look up the official documentation (as is most of this wiki).
Group object attributes
The first set of six lines describe an object of class posixGroup. The posixGroup class is part of the NIS schema, and an object of this class is "an abstraction of a group of accounts" (according to the description with the class definition. This means that in our example, the object with distinguished name cn=networkusers,ou=groups,dc=saruman,dc=biz will be a representation of one single group as we know it from /etc/group. So how do the six lines together define this single group? Let's look at the entries again:
# Create the user group dn: cn=networkusers,ou=groups,dc=saruman,dc=biz objectClass: posixGroup gidNumber: 10001 cn: TestGroup description: Internal network users
- The first line begins with a hash sign (#) making it a comment. It does nothing to create the object, only to clarify the LDIF file. We recomment strongly in favour of using comments, whenever your LDIF file must be kept longer than 10 minutes after creation :-).
- dn: means the Distinguished Name; it tells the LDIF that this is the dn with which to address the object.
- objectClass: this defines what attributes the object must and may have. Want to know which attributes? Look into /etc/ldap/schema/nis.schema and find the string 'posixGroup'. You'll see that the mandatory attributes are cn and gidNumber, and optional attributes userPassword, memberUid and description
- gidNumber: mandatory attribute, that holds the "numerical value of the group's ID"
- cn: this is the second mandatory attribute, and holds the name of the group. We could also have used the full attribute name commonName:, but really "cn" is the prevalent form.
- description: hey, that's one of them optional attributes! It has no equivalent in the Posix group definition, but it can ofcourse clarify the purpose of said group in the LDAP directory.
Since there's an empty line after these six lines, the rest of the LDIF file does not concern this particular group object; a set of adjacent lines are held to be a declaration of one single object.
It should be clear that the above information is sufficient to create in LDAP an object that holds all information that any POSIX compliant group would need. Creating an object of type posixGroup in this manner makes it possible to use the object in LDAP as if it were a group on the local Linux/Unix machine, i.e. it can map directly to a Linux/Unix group.
User object attributes
The next section of this particular LDIF file consists of 22 adjacent lines, of which five begin with a hash sign. The other 17 lines define the actual object. So how does this object form in LDAP when you feed it this LDIF file? Here is that section again, stripped of its comments:
dn: uid=sixpacjo,ou=people,dc=saruman,dc=biz objectClass: top objectClass: posixAccount objectClass: shadowAccount objectClass: inetOrgPerson cn: Joe Sixpack description: Your Average Network User givenName: Joe sn: Sixpack mail: joe.sixpack@saruman.biz mail: j.sixpack@saruman.biz uid: sixpacjo gidNumber: 10001 uidNumber: 10001 homeDirectory: /home/sixpacjo loginShell: /bin/bash userPassword: {crypt}$1$qs70ynbk$UBuewN7ZdIvqavIxkxdmX0
- dn: again tells the LDIF that this is the Distinguished Name with which to address the object.
- four lines of objectClass:: these multiple lines tell OpenLDAP that the object has all the attributes that are described in those four classes (top, inetOrgPerson, posixAccount and shadowAccount).
- class top: this is a special class ("abstract" class) that actually doesn't even exist. It is the root of the tree of classes we're going to use. If you leave this class out, it doesn't change a bit (the presence of this class is always implied). So why put it in? We don't know, it's sort of a best practice, we think...
- class posixAccount: defined in the nis.schema file. Contains five mandatory attributes plus four optional, that together contain all necessary information to create a Linux user account.
- class shadowAccount: defined in the nis.schema file. Contains the mandatory attribute uid and nine optional attributes that can be used to maintain shadow passwords - as does Linux. The uid attribute, as well as optional attributes userPassword and description also appear in class posixAccount, so adding this class to our user object actually only provides seven additional optional attributes.
- class inetOrgPerson: defined in the dedicated inetorgperson.schema file, it contains 27 optional attributes. We want these in our LDAP account mainly because it gives us the attribute mail that we forsee we'll be using to add LDAP support to our mail server solution.
- cn: is again the Common Name. In the context of a person's LDAP account, you may read "full name". Hence the full name "Joe Sixpack" in there. When using the useradd command under Linux, we usually put this information in the "comment" field (useradd -c "Joe Sixpack" sixpajo).
- description: is again an optional attribute; we use it here to clarify the status of the account.
- givenName: is a field that we use to hold the user's first name ("Joe").
- sn: contains the surname, or as the core.schema definition says: "'RFC2256: last (family) name(s) for which the entity is known by".
- mail: is the (optional) field from the inetOrgPerson class that holds the person's email address or addresses (in RFC822 format). As it can be multi-valued, we've specified it twice for Joe.
- uid: or userid: is the single-valued unique "RFC1274: user identifier" that we designate to be the user's login name.
- gidNumber: according to the nis.schema file this holds "An integer uniquely identifying a group in an administrative domain"; we can thus use it as the group ID number under Linux.
- uidNumber: - Like the gidNumber this is "An integer uniquely identifying a user in an administrative domain"; we can use it as the Linux user ID number.
- homeDirectory: - This case sensitive single-value attribute holds the absolute path to the user's home directory.
- loginShell: is also case sensitive, single-valued, and contains - wait for it... - the user's login shell!!
- userPassword: comes from the core.schema file, and contains "RFC2256/2307: password of user". Usually, the password in this field is encrypted. When defining a new user, putting an encrypted value for the password in here takes some extra effort, as explained in the section below
Specifying passwords in LDIF files
So in the previous we've read that the userPassword attribute must be specified in an encrypted form. "AHA!" you'll say. "But how do I obtain such an encrypted password?" Fortunately, that's quite simple. Try this:
openssl passwd -crypt "secret"
The argument -crypt makes openssl generate a password using the standard Unix password algorithm; this is also the default setting. An alternative would be to use -1 instead of -crypt, which'll give you an MD5 encrypted password. Ofcourse, using an MD5 encrypted password means you have to change the last line of the LDIF file to something like
userPassword: {MD5}$1$yCuyTf63$NoAjuX/dYBmE29hXrsDb41
Note that prefixing the used encryption method is totally fine with OpenLDAP, but it actually is not according to the LDAP standard; this LDIF file can be understood by OpenLDAP, but not by every other piece of LDAP software out there... However, since this is actually a Linux oriented Wiki, and we're discussing OpenLDAP here, we're going to say: put the encryption type in!