directory /var/lib/openldap-data
index objectClass eq
-Note that [inetorgperson][] is huge, but it's standardized. I think
-it's better to pick a big standard right off, than to outgrow
-something smaller and need to migrate.
+[inetOrgPerson][] is huge, but it's standardized. I think it's better
+to pick a big standard right off, than to outgrow something smaller
+and need to migrate.
Gentoo creates the default database directory for you, so you can
ignore warnings about needing to create it yourself.
You can search for all entries (including aliases) with
$ ldapsearch -x -b 'ou=test, dc=example,dc=com' '(objectclass=*)'
- ...
+ …
dn: cn=Jane Doe,ou=test,dc=example,dc=com
objectClass: alias
objectClass: extensibleObject
aliasedObjectName:: Y249TWljaGVsIFZhbGxpw6hyZXMsb3U9cGVvcGxlLGRjPXRyZW1pbHksZGM9dXM=
- ...
+ …
You can control dereferencing with the `-a` option:
$ ldapsearch -x -a always -b 'ou=test, dc=example,dc=com' '(objectclass=*)'
- ...
+ …
dn: cn=Jane Doe,ou=people,dc=example,dc=com
cn: Jane Doe
sn: Doe
- ...
+ …
Once you've played around, you can remove the `test` OU and its
descendants:
populated by the entry you're editing. You can either alter the entry
as you see fit, or try something fancier in [LDIF][].
+JPEG photos and binary data
+---------------------------
+
+[inetOrgPerson][] has a [jpegPhoto][] attribute, which holds a base64
+encoded JPEG. The easiest way to set this attribute is to use the
+`:<` delimiter mentioned in `ldif(5)` and [RFC 2849][rfc2849]:
+
+ $ cat thumb.ldif
+ version: 1
+ dn: cn=Jane Doe,ou=people,dc=example,dc=com
+ changetype: modify
+ add: jpegPhoto
+ jpegPhoto:< file:///tmp/jdoe.jpeg
+ -
+ $ ldapmodify -f thumb.ldif
+
+You can extract the thumbnail from the database using:
+
+ $ ldapsearch -tT /tmp "cn=Jane Doe"
+ …
+ jpegPhoto:< file:///tmp/ldapsearch-jpegPhoto-Vvg2Ot
+ …
+
+Which dumps non-printable values (like our `jpegPhoto`) to temporary
+files.
+
+If you just want to look up someone's picture, take a look at my
+[[ldap-jpeg.py]] script. It searches for a query string in any of
+[cn][], [uid][], or [mail][], and for matching entries with a
+`jpegPhoto` attribute, it uses your [[mailcap]]-specified viewer to
+display the photo.
+
Mutt
----
port = 636
ssl = yes
+Access control and authentication
+---------------------------------
+
+There are a number of possible approaches to authentication for LDAP,
+so read the [admin manual][admin] for details. I've got [[Kerberos]]
+setup on my home system, and I'll walk through this setup here.
+
+### Server side
+
+I expose the LDAPS port to the external world through my router, and I
+don't want anonymous users to be able to download all my contact
+information. The solution to this is to implement [access
+control][access]. For my situation, the following
+`/etc/openldap/slapd.conf` directives seemed appropriate:
+
+ access to attrs=uid
+ by anonymous auth
+ by * read
+
+ access to *
+ by self write
+ by anonymous auth
+ by * read
+
+The first directive allows anonymous users to use the [uid][]
+attribute when authenticating, and allows authenticated users to read
+anyone's `uid` attribute. This keeps users from being able to change
+their own `uid`.
+
+The second directive allows authenticated users to update their own
+entry and to read every entry. Anonymous are allowed to authenticate
+themselves, but have no other privileges.
+
+Alright, so how should user's go about authenticating][security]?
+We'll want to set `slapd` up as a Kerberos service, and have clients
+authenticate using [GSSAPI][].
+
+For the LDAP service, we'll need a `ldap/<fqdn>@REALM` principal.
+Because we want that service to start automatically at boot, we need
+to keep its key in a keytab file.
+
+ # kadmin.local -p jdoe/admin
+ Authenticating as principal jdoe/admin with password.
+ Password for jdoe/admin@R.EDU:
+ kadmin.local: add_principal -randkey ldap/ldapserver.example.com
+ WARNING: no policy specified for ldap/ldapserver.example.com@R.EDU; defaulting to no policy
+ Principal "ldap/ldapserver.example.com@R.EDU" created.
+ kadmin.local: ktadd -k /etc/openldap/krb5-ldap.keytab ldap/ldapserver.example.com
+ Entry for principal kdap/ldapserver.example.com...
+ …
+ kadmin.local: quit
+ # chown ldap:ldap /etc/openldap/krb5-ldap.keytab
+
+You need use `kadmin.local` here (instead of `kadmin`) so the process
+has premission to create and edit the keytab file.
+
+You'll need to point your `slapd` server to the new keytab. On
+[[Gentoo]], you do this by uncommenting
+
+ KRB5_KTNAME=/etc/openldap/krb5-ldap.keytab
+
+in `/etc/conf.d/slapd`. On Red Hat, you add
+
+ export KRB5_KTNAME=/etc/openldap/ldap.keytab
+
+to `/etc/sysconfig/ldap`.
+
+You should also configure your realm and hostname in
+`/etc/openldap/slapd.conf`:
+
+ sasl-realm R.EDU
+ sasl-host ldapserver.example.com
+
+You'll also want to associate user's Kerberos principles to LDAP DNs.
+The template `slapd` uses is:
+
+ uid=<primary[/instance]>,cn=<realm>,cn=gssapi,cn=auth
+
+so `jdoe@R.EDU` is associated with
+
+ uid=jdoe,cn=r.edu,cn=gssapi,cn=auth
+
+and `jdoe/admin@R.EDU` is associated with
+
+ uid=jdoe/admin,cn=r.edu,cn=gssapi,cn=auth
+
+You'll probably want to [map these authentication DNs][map] to the
+appropriate directory entry, for example:
+
+ cn=Jane Doe,ou=people,dc=r,dc=edu
+
+There are a number of ways to this, but I chose
+
+ authz-regexp
+ uid=([^,]*),cn=r.edu,cn=gssapi,cn=auth
+ ldap:///ou=people,dc=r,dc=edu??one?(uid=$1)
+
+From the manual:
+
+> This will initiate an internal search of the LDAP database inside
+> the slapd server. If the search returns exactly one entry, it is
+> accepted as being the DN of the user. If there are more than one
+> entries returned, or if there are zero entries returned, the
+> authentication fails and the user's connection is left bound as the
+> authentication request DN.
+
+[Indexing][index] sounds like a good idea, so we turn it on with
+
+ index cn,sn,mail,uid eq
+ index cn,mail sub
+
+If you change your index configuration, you'll have to stop `slapd`
+and run `slapindex` to regenerate the indexes.
+
+### Client side
+
+Users will have to do the usual `kinit` to get their Ticket Granting
+Ticket (TGT), and then instruct their client software to use GSSAPI
+(`-Y GSSAPI` with the OpenLDAP client tools). If you don't want to
+type `-Y GSSAPI`, you can add
+
+ SASL_MECH GSSAPI
+
+to your `~/.ldaprc`. If you're on Gentoo, you'll want the `kerberos`
+and `sasl` `USE` flags set when you emerge `openldap`.
+
+#### Reverse DNS issues
+
+Because my SLAPD server runs on a dynamic IP address, I ran into
+trouble with reverse DNS. The client would resolve the server address
+into an IP, then resolve that IP address to its canonical name, and
+asks the ticket granting server (TGS) for authorization to use
+`ldap/<canonical>@REALM`. Because the dynamic canonical name doesn't
+match the hostname, the TGS denies the request, leading to output
+like:
+
+ $ ldapwhoami -Y GSSAPI
+ ldap_sasl_interactive_bind_s: Local error (-2)
+ additional info: SASL(-1): generic failure: GSSAPI Error: Unspecified GSS failure. Minor code may provide more information (Server krbtgt/EDU@R.EDU not found in Kerberos database)
+
+And messages like:
+
+ … krb5kdc[15239](info): TGS_REQ (4 etypes {18 17 16 23}) …: UNKNOWN_SERVER: authtime 0, jdoe@R.EDU for host/some.dynamic.canonical.host.net@R.EDU, Server not found in Kerberos database
+
+in the server's KDC log.
+
+I tried disabling the reverse DNS lookup with both the `-N` command
+line option to `ldapwhoami` and the `SASL_NOCANON true` option in
+`~/.ldaprc`. I also added:
+
+ [libdefaults]
+ rdns = false
+
+to my client's `/etc/krb5.conf`. Even with all of these, I was still
+getting reverse DNS attempts, so I gave up and just added an entry to
+`/etc/hosts` to ensure I got the right hostname when the client tried
+to resolve it.
+
+You can get more detailed messages from `ldapwhoami` by increasing the
+debuglevel (for example, with the `-d 1` option), which helps when
+you're troubleshooting these kinds of issues. For example:
+
+ $ ldapwhoami -d 1 -Y GSSAPI -d 1
+ …
+ ldap_int_sasl_open: host=some.dynamic.canonical.host.net
+ …
+ $ ldapwhoami -d 1 -Y GSSAPI -N -d 1
+ …
+ ldap_int_sasl_open: host=ldapserver.example.com
+ …
+
+Currently, `ldapwhoami` and friends will ignore the `SASL_NOCANON`
+configuration option and only respect the `-N` command line option.
+I've submitted [an OpenLDAP bug][7271] fixing this, but there is still
+a reverse DNS call happening at some point.
+
Debian-based systems
--------------------
Don't serve in the clear:
$ cat /etc/default/slapd
- ...
+ …
SLAPD_SERVICES="ldaps:/// ldapi:///"
- ...
+ …
Avoid `Unrecognized database type (hdb)` by loading the `hdb` backend
module before declaring `hdb` databases:
$ sudo cat /etc/ldap/slapd.conf
- ...
+ …
moduleload back_hdb
database hdb
- ...
+ …
Convert the old school `slapd.conf` to the new [slapd.d][]:
$ sudo mv slapd.d{,.bak}
$ sudo mkdir slapd.d
$ sudo slaptest -f slapd.conf -F slapd.d
- ...
+ …
hdb_db_open: database "dc=example,dc=com": db_open(/var/lib/slapd/id2entry.bdb) failed: No such file or directory (2).
- ...
+ …
slap_startup failed (test would succeed using the -u switch)
- ...
+ …
$ sudo chown -R openldap.openldap slapd.d
Don't worry about that `db_open` error, the conversion to `slapd.d`
[howto]: http://www.gentoo.org/doc/en/ldap-howto.xml
[OpenLDAP]: http://www.openldap.org/
[admin]: http://www.openldap.org/doc/admin/
-[inetorgperson]: http://www.apps.ietf.org/rfc/rfc2798.html
+[inetOrgPerson]: http://tools.ietf.org/html/rfc2798
[abook]: http://abook.sourceforge.net/
[LDIF]: http://en.wikipedia.org/wiki/LDAP_Data_Interchange_Format
[python-ldap]: http://www.python-ldap.org/
[rfc4512]: http://tools.ietf.org/html/rfc4512
[shelldap]: http://projects.martini.nu/shelldap/
+[jpegPhoto]: http://tools.ietf.org/html/rfc2798#section-2.6
+[cn]: http://tools.ietf.org/html/rfc2798#section-9.1.2
+[uid]: http://tools.ietf.org/html/rfc2798#page-16
+[mail]: http://tools.ietf.org/html/rfc2798#section-9.1.3
+[jpegPhoto]: http://tools.ietf.org/html/rfc2798#section-2.6
+[rfc2849]: http://tools.ietf.org/html/rfc2849
[mutts]: http://wiki.mutt.org/?QueryCommand
[aab]: http://support.apple.com/kb/ht2486
[SSL/TLS]: http://en.wikipedia.org/wiki/Transport_Layer_Security
[certtool]:http://www.gnu.org/software/gnutls/manual/html_node/Invoking-certtool.html#Invoking-certtool
+[access]: http://www.openldap.org/doc/admin24/access-control.html
+[security]: http://www.openldap.org/doc/admin24/security.html
+[GSSAPI]: http://en.wikipedia.org/wiki/Generic_Security_Services_Application_Program_Interface
+[map]: http://www.openldap.org/doc/admin24/sasl.html#Mapping%20Authentication%20Identities
+[index]: http://www.openldap.org/doc/admin24/tuning.html#Indexes
+[7271]: http://www.openldap.org/its/index.cgi?findid=7271
[slapd.d]: http://www.openldap.org/doc/admin24/slapdconf2.html
[schema]: http://www.oreillynet.com/pub/a/sysadmin/2006/11/09/demystifying-ldap-data.html