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.
+Gentoo creates the default database directory for you, so you can
+ignore warnings about needing to create it yourself.
Configure LDAP client access. Again, read the docs for details on
adapting this to your particular situation:
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:
~ > cd ou=people
ou=people,~ > ls
+Shelldap's `edit` command spawns your `EDITOR` on a temporary file
+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
----
If you use the [[Mutt]] email client (or just want a simple way to
query email addresses from the command line) there are a [number of
scripts][mutts] available. Pick whichever sounds most appealing to
-you. I wrote up [[mutt-ldap.py]], which lets you configuration the
-connection details via a config file (`~/.mutt-ldap.rc`) rather than
-editing the script itself. Usage details are available in the
-docstring.
+you. I wrote up [[mutt-ldap.py|mutt-ldap]], which has since seen
+contributions from others and been pulled out into its own repository.
Apple Address Book
------------------
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 objectClass eq
+ index 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
+ …
+ ldap_int_sasl_open: host=some.dynamic.canonical.host.net
+ …
+ $ ldapwhoami -d 1 -Y GSSAPI -N
+ …
+ 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 (included in
+version 2.4.32, 2012-07-31), but there is still a reverse DNS call
+happening at some point.
+
+Debian-based systems
+--------------------
+
+I wanted to mirror my home LDAP info on my public Ubuntu server.
+Here's a quick rundown of the Ubuntu setup. Install OpenLDAP:
+
+ $ sudo apt-get install slapd ldap-utils
+
+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`
+will have completed successfully.
+
+Set permissions on the database directory (note that the databases
+should be under `/var/lib/ldap` to match Ubuntu's default apparmor
+config. Otherwise you'll see `invalid path: Permission denied` errors
+when `slapd` tries to initialize the databaes).
+
+ $ sudo chown openldap.openldap /var/lib/ldap/
+ $ sudo chmod 750 /var/lib/ldap/
+
+Configure your clients
+
+ $ cat /etc/ldap/ldap.conf
+ BASE dc=example,dc=com
+ URI ldaps://example.com
+ TLS_CACERT /etc/ldap/ssl/ldapserver.crt
+
+Start `slapd` and add it to your default runlevel:
+
+ $ sudo /etc/init.d/slapd start
+ $ sudo update-rc.d slapd defaults
+
+Finally, import your directory data. Dump the data on your master
+server:
+
+ master$ sudo slapcat -b 'dc=example,dc=com' > database.ldif
+
+Load the data on your slave:
+
+ $ sudo /etc/init.d/slapd stop
+ $ sudo slapadd -l database.ldif
+ $ sudo /etc/init.d/slapd start
+
References
----------
[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
[[!tag tags/linux]]