LDIF syntax explanation

From SaruWiki
Revision as of 14:47, 27 September 2008 by Saruman! (talk | contribs) (→‎Specifying passwords in LDIF files: added slappasswd instead of openssl as pw hasher)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

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 ("hashed" would be a better term, but there you go....). "AHA!" you'll say. "But how do I obtain such an encrypted password?" Fortunately, that's quite simple. Try this:

slappasswd -u -h {SSHA} -s secret

The argument -u tells slappasswd that you're interested in generating an RFC 2307 compliant userPassword (this is the default, so you could leave out the -u). The -h {SSHA} tells the command to use SSHA as hashing method, and -s secret specifies that you want to hash the word "secret". If you want to hash password "H4ckm3!", you'd get something like this:

slappasswd -u -h {SSHA} -s H4ckm3!
{SSHA}uPeS2Pxi4pzTPNOx+ZUVh21WPPeyJWrV

You can take the hash string, inclusive of the {SSHA} prefix, and put it in an LDIF file for processing by OpenLDAP; it will 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!