summaryrefslogtreecommitdiffstats
path: root/README_FILES/LDAP_README
diff options
context:
space:
mode:
Diffstat (limited to 'README_FILES/LDAP_README')
-rw-r--r--README_FILES/LDAP_README465
1 files changed, 465 insertions, 0 deletions
diff --git a/README_FILES/LDAP_README b/README_FILES/LDAP_README
new file mode 100644
index 0000000..eeef565
--- /dev/null
+++ b/README_FILES/LDAP_README
@@ -0,0 +1,465 @@
+PPoossttffiixx LLDDAAPP HHoowwttoo
+
+-------------------------------------------------------------------------------
+
+LLDDAAPP SSuuppppoorrtt iinn PPoossttffiixx
+
+Postfix can use an LDAP directory as a source for any of its lookups: aliases
+(5), virtual(5), canonical(5), etc. This allows you to keep information for
+your mail service in a replicated network database with fine-grained access
+controls. By not storing it locally on the mail server, the administrators can
+maintain it from anywhere, and the users can control whatever bits of it you
+think appropriate. You can have multiple mail servers using the same
+information, without the hassle and delay of having to copy it to each.
+
+Topics covered in this document:
+
+ * Building Postfix with LDAP support
+ * Configuring LDAP lookups
+ * Example: aliases
+ * Example: virtual domains/addresses
+ * Example: expanding LDAP groups
+ * Other uses of LDAP lookups
+ * Notes and things to think about
+ * Feedback
+ * Credits
+
+BBuuiillddiinngg PPoossttffiixx wwiitthh LLDDAAPP ssuuppppoorrtt
+
+These instructions assume that you build Postfix from source code as described
+in the INSTALL document. Some modification may be required if you build Postfix
+from a vendor-specific source package.
+
+Note 1: Postfix no longer supports the LDAP version 1 interface.
+
+Note 2: to use LDAP with Debian GNU/Linux's Postfix, all you need is to install
+the postfix-ldap package and you're done. There is no need to recompile
+Postfix.
+
+You need to have LDAP libraries and include files installed somewhere on your
+system, and you need to configure the Postfix Makefiles accordingly.
+
+For example, to build the OpenLDAP libraries for use with Postfix (i.e. LDAP
+client code only), you could use the following command:
+
+ % ./configure --without-kerberos --without-cyrus-sasl --without-tls \
+ --without-threads --disable-slapd --disable-slurpd \
+ --disable-debug --disable-shared
+
+If you're using the libraries from the UM distribution (http://www.umich.edu/
+~dirsvcs/ldap/ldap.html) or OpenLDAP (http://www.openldap.org), something like
+this in the top level of your Postfix source tree should work:
+
+ % make tidy
+ % make makefiles CCARGS="-I/usr/local/include -DHAS_LDAP" \
+ AUXLIBS_LDAP="-L/usr/local/lib -lldap -L/usr/local/lib -llber"
+
+If your LDAP shared library is in a directory that the RUN-TIME linker does not
+know about, add a "-Wl,-R,/path/to/directory" option after "-lldap".
+
+Postfix versions before 3.0 use AUXLIBS instead of AUXLIBS_LDAP. With Postfix
+3.0 and later, the old AUXLIBS variable still supports building a statically-
+loaded LDAP database client, but only the new AUXLIBS_LDAP variable supports
+building a dynamically-loaded or statically-loaded LDAP database client.
+
+ Failure to use the AUXLIBS_LDAP variable will defeat the purpose of dynamic
+ database client loading. Every Postfix executable file will have LDAP
+ database library dependencies. And that was exactly what dynamic database
+ client loading was meant to avoid.
+
+On Solaris 2.x you may have to specify run-time link information, otherwise
+ld.so will not find some of the shared libraries:
+
+ % make tidy
+ % make makefiles CCARGS="-I/usr/local/include -DHAS_LDAP" \
+ AUXLIBS_LDAP="-L/usr/local/lib -R/usr/local/lib -lldap \
+ -L/usr/local/lib -R/usr/local/lib -llber"
+
+The 'make tidy' command is needed only if you have previously built Postfix
+without LDAP support.
+
+Instead of '/usr/local' specify the actual locations of your LDAP include files
+and libraries. Be sure to not mix LDAP include files and LDAP libraries of
+different versions!!
+
+If your LDAP libraries were built with Kerberos support, you'll also need to
+include your Kerberos libraries in this line. Note that the KTH Kerberos IV
+libraries might conflict with Postfix's lib/libdns.a, which defines dns_lookup.
+If that happens, you'll probably want to link with LDAP libraries that lack
+Kerberos support just to build Postfix, as it doesn't support Kerberos binds to
+the LDAP server anyway. Sorry about the bother.
+
+If you're using one of the Netscape LDAP SDKs, you'll need to change the
+AUXLIBS line to point to libldap10.so or libldapssl30.so or whatever you have,
+and you may need to use the appropriate linker option (e.g. '-R') so the
+executables can find it at runtime.
+
+If you are using OpenLDAP, and the libraries were built with SASL support, you
+can add -DUSE_LDAP_SASL to the CCARGS to enable SASL support. For example:
+
+ CCARGS="-I/usr/local/include -DHAS_LDAP -DUSE_LDAP_SASL"
+
+CCoonnffiigguurriinngg LLDDAAPP llooookkuuppss
+
+In order to use LDAP lookups, define an LDAP source as a table lookup in
+main.cf, for example:
+
+ alias_maps = hash:/etc/aliases, ldap:/etc/postfix/ldap-aliases.cf
+
+The file /etc/postfix/ldap-aliases.cf can specify a great number of parameters,
+including parameters that enable LDAP SSL or STARTTLS, and LDAP SASL. For a
+complete description, see the ldap_table(5) manual page.
+
+EExxaammppllee:: llooccaall((88)) aalliiaasseess
+
+Here's a basic example for using LDAP to look up local(8) aliases. Assume that
+in main.cf, you have:
+
+ alias_maps = hash:/etc/aliases, ldap:/etc/postfix/ldap-aliases.cf
+
+and in ldap:/etc/postfix/ldap-aliases.cf you have:
+
+ server_host = ldap.example.com
+ search_base = dc=example, dc=com
+
+Upon receiving mail for a local address "ldapuser" that isn't found in the /
+etc/aliases database, Postfix will search the LDAP server listening at port 389
+on ldap.example.com. It will bind anonymously, search for any directory entries
+whose mailacceptinggeneralid attribute is "ldapuser", read the "maildrop"
+attributes of those found, and build a list of their maildrops, which will be
+treated as RFC822 addresses to which the message will be delivered.
+
+EExxaammppllee:: vviirrttuuaall ddoommaaiinnss//aaddddrreesssseess
+
+If you want to keep information for virtual lookups in your directory, it's
+only a little more complicated. First, you need to make sure Postfix knows
+about the virtual domain. An easy way to do that is to add the domain to the
+mailacceptinggeneralid attribute of some entry in the directory. Next, you'll
+want to make sure all of your virtual recipient's mailacceptinggeneralid
+attributes are fully qualified with their virtual domains. Finally, if you want
+to designate a directory entry as the default user for a virtual domain, just
+give it an additional mailacceptinggeneralid (or the equivalent in your
+directory) of "@fake.dom". That's right, no user part. If you don't want a
+catchall user, omit this step and mail to unknown users in the domain will
+simply bounce.
+
+In summary, you might have a catchall user for a virtual domain that looks like
+this:
+
+ dn: cn=defaultrecipient, dc=fake, dc=dom
+ objectclass: top
+ objectclass: virtualaccount
+ cn: defaultrecipient
+ owner: uid=root, dc=someserver, dc=isp, dc=dom
+ 1 -> mailacceptinggeneralid: fake.dom
+ 2 -> mailacceptinggeneralid: @fake.dom
+ 3 -> maildrop: realuser@real.dom
+
+ 1: Postfix knows fake.dom is a valid virtual domain when it looks for this
+ and gets something (the maildrop) back.
+
+ 2: This causes any mail for unknown users in fake.dom to go to this entry
+ ...
+
+ 3: ... and then to its maildrop.
+
+Normal users might simply have one mailacceptinggeneralid and maildrop, e.g.
+"normaluser@fake.dom" and "normaluser@real.dom".
+
+EExxaammppllee:: eexxppaannddiinngg LLDDAAPP ggrroouuppss
+
+LDAP is frequently used to store group member information. There are a number
+of ways of handling LDAP groups. We will show a few examples in order of
+increasing complexity, but owing to the number of independent variables, we can
+only present a tiny portion of the solution space. We show how to:
+
+ 1. query groups as lists of addresses;
+
+ 2. query groups as lists of user objects containing addresses;
+
+ 3. forward special lists unexpanded to a separate list server, for moderation
+ or other processing;
+
+ 4. handle complex schemas by controlling expansion and by treating leaf nodes
+ specially, using features that are new in Postfix 2.4.
+
+The example LDAP entries and implied schema below show two group entries
+("agroup" and "bgroup") and four user entries ("auser", "buser", "cuser" and
+"duser"). The group "agroup" has the users "auser" (1) and "buser" (2) as
+members via DN references in the multi-valued attribute "memberdn", and direct
+email addresses of two external users "auser@example.org" (3) and
+"buser@example.org" (4) stored in the multi-valued attribute "memberaddr". The
+same is true of "bgroup" and "cuser"/"duser" (6)/(7)/(8)/(9), but "bgroup" also
+has a "maildrop" attribute of "bgroup@mlm.example.com" (5):
+
+ dn: cn=agroup, dc=example, dc=com
+ objectclass: top
+ objectclass: ldapgroup
+ cn: agroup
+ mail: agroup@example.com
+ 1 -> memberdn: uid=auser, dc=example, dc=com
+ 2 -> memberdn: uid=buser, dc=example, dc=com
+ 3 -> memberaddr: auser@example.org
+ 4 -> memberaddr: buser@example.org
+
+ dn: cn=bgroup, dc=example, dc=com
+ objectclass: top
+ objectclass: ldapgroup
+ cn: bgroup
+ mail: bgroup@example.com
+ 5 -> maildrop: bgroup@mlm.example.com
+ 6 -> memberdn: uid=cuser, dc=example, dc=com
+ 7 -> memberdn: uid=duser, dc=example, dc=com
+ 8 -> memberaddr: cuser@example.org
+ 9 -> memberaddr: duser@example.org
+
+ dn: uid=auser, dc=example, dc=com
+ objectclass: top
+ objectclass: ldapuser
+ uid: auser
+ 10 -> mail: auser@example.com
+ 11 -> maildrop: auser@mailhub.example.com
+
+ dn: uid=buser, dc=example, dc=com
+ objectclass: top
+ objectclass: ldapuser
+ uid: buser
+ 12 -> mail: buser@example.com
+ 13 -> maildrop: buser@mailhub.example.com
+
+ dn: uid=cuser, dc=example, dc=com
+ objectclass: top
+ objectclass: ldapuser
+ uid: cuser
+ 14 -> mail: cuser@example.com
+
+ dn: uid=duser, dc=example, dc=com
+ objectclass: top
+ objectclass: ldapuser
+ uid: duser
+ 15 -> mail: duser@example.com
+
+Our first use case ignores the "memberdn" attributes, and assumes that groups
+hold only direct "memberaddr" strings as in (3), (4), (8) and (9). The goal is
+to map the group address to the list of constituent "memberaddr" values. This
+is simple, ignoring the various connection related settings (hosts, ports, bind
+settings, timeouts, ...) we have:
+
+ simple.cf:
+ ...
+ search_base = dc=example, dc=com
+ query_filter = mail=%s
+ result_attribute = memberaddr
+ $ postmap -q agroup@example.com ldap:/etc/postfix/simple.cf \
+ auser@example.org,buser@example.org
+
+We search "dc=example, dc=com". The "mail" attribute is used in the
+query_filter to locate the right group, the "result_attribute" setting
+described in ldap_table(5) is used to specify that "memberaddr" values from the
+matching group are to be returned as a comma separated list. Always check
+tables using postmap(1) with the "-q" option, before deploying them into
+production use in main.cf.
+
+Our second use case instead expands "memberdn" attributes (1), (2), (6) and
+(7), follows the DN references and returns the "maildrop" of the referenced
+user entries. Here we use the "special_result_attribute" setting from
+ldap_table(5) to designate the "memberdn" attribute as holding DNs of the
+desired member entries. The "result_attribute" setting selects which attributes
+are returned from the selected DNs. It is important to choose a result
+attribute that is not also present in the group object, because result
+attributes are collected from both the group and the member DNs. In this case
+we choose "maildrop" and assume for the moment that groups never have a
+"maildrop" (the "bgroup" "maildrop" attribute is for a different use case). The
+returned data for "auser" and "buser" is from items (11) and (13) in the
+example data.
+
+ special.cf:
+ ...
+ search_base = dc=example, dc=com
+ query_filter = mail=%s
+ result_attribute = maildrop
+ special_result_attribute = memberdn
+ $ postmap -q agroup@example.com ldap:/etc/postfix/special.cf \
+ auser@mailhub.example.com,buser@mailhub.example.com
+
+Note: if the desired member object result attribute is always also present in
+the group, you get surprising results: the expansion also returns the address
+of the group. This is a known limitation of Postfix releases prior to 2.4, and
+is addressed in the new with Postfix 2.4 "leaf_result_attribute" feature
+described in ldap_table(5).
+
+Our third use case has some groups that are expanded immediately, and other
+groups that are forwarded to a dedicated mailing list manager host for delayed
+expansion. This uses two LDAP tables, one for users and forwarded groups and a
+second for groups that can be expanded immediately. It is assumed that groups
+that require forwarding are never nested members of groups that are directly
+expanded.
+
+ no_expand.cf:
+ ...
+ search_base = dc=example, dc=com
+ query_filter = mail=%s
+ result_attribute = maildrop
+ expand.cf
+ ...
+ search_base = dc=example, dc=com
+ query_filter = mail=%s
+ result_attribute = maildrop
+ special_result_attribute = memberdn
+ $ postmap -q auser@example.com \
+ ldap:/etc/postfix/no_expand.cf ldap:/etc/postfix/expand.cf \
+ auser@mailhub.example.com
+ $ postmap -q agroup@example.com \
+ ldap:/etc/postfix/no_expand.cf ldap:/etc/postfix/expand.cf \
+ auser@mailhub.example.com,buser@mailhub.example.com
+ $ postmap -q bgroup@example.com \
+ ldap:/etc/postfix/no_expand.cf ldap:/etc/postfix/expand.cf \
+ bgroup@mlm.example.com
+
+Non-group objects and groups with delayed expansion (those that have a maildrop
+attribute) are rewritten to a single maildrop value. Groups that don't have a
+maildrop are expanded as the second use case. This admits a more elegant
+solution with Postfix 2.4 and later.
+
+Our final use case is the same as the third, but this time uses new features in
+Postfix 2.4. We now are able to use just one LDAP table and no longer need to
+assume that forwarded groups are never nested inside expanded groups.
+
+ fancy.cf:
+ ...
+ search_base = dc=example, dc=com
+ query_filter = mail=%s
+ result_attribute = memberaddr
+ special_result_attribute = memberdn
+ terminal_result_attribute = maildrop
+ leaf_result_attribute = mail
+ $ postmap -q auser@example.com ldap:/etc/postfix/fancy.cf \
+ auser@mailhub.example.com
+ $ postmap -q cuser@example.com ldap:/etc/postfix/fancy.cf \
+ cuser@example.com
+ $ postmap -q agroup@example.com ldap:/etc/postfix/fancy.cf \
+
+ auser@mailhub.example.com,buser@mailhub.example.com,auser@example.org,buser@example.org
+ $ postmap -q bgroup@example.com ldap:/etc/postfix/fancy.cf \
+ bgroup@mlm.example.com
+
+Above, delayed expansion is enabled via "terminal_result_attribute", which, if
+present, is used as the sole result and all other expansion is suppressed.
+Otherwise, the "leaf_result_attribute" is only returned for leaf objects that
+don't have a "special_result_attribute" (non-groups), while the
+"result_attribute" (direct member address of groups) is returned at every level
+of recursive expansion, not just the leaf nodes. This fancy example illustrates
+all the features of Postfix 2.4 group expansion.
+
+OOtthheerr uusseess ooff LLDDAAPP llooookkuuppss
+
+Other common uses for LDAP lookups include rewriting senders and recipients
+with Postfix's canonical lookups, for example in order to make mail leaving
+your site appear to be coming from "First.Last@example.com" instead of
+"userid@example.com".
+
+NNootteess aanndd tthhiinnggss ttoo tthhiinnkk aabboouutt
+
+ * The bits of schema and attribute names used in this document are just
+ examples. There's nothing special about them, other than that some are the
+ defaults in the LDAP configuration parameters. You can use whatever schema
+ you like, and configure Postfix accordingly.
+
+ * You probably want to make sure that mailacceptinggeneralids are unique, and
+ that not just anyone can specify theirs as postmaster or root, say.
+
+ * An entry can have an arbitrary number of mailacceptinggeneralids or
+ maildrops. Maildrops can also be comma-separated lists of addresses. They
+ will all be found and returned by the lookups. For example, you could
+ define an entry intended for use as a mailing list that looks like this
+ (Warning! Schema made up just for this example):
+
+ dn: cn=Accounting Staff List, dc=example, dc=com
+ cn: Accounting Staff List
+ o: example.com
+ objectclass: maillist
+ mailacceptinggeneralid: accountingstaff
+ mailacceptinggeneralid: accounting-staff
+ maildrop: mylist-owner
+ maildrop: an-accountant
+ maildrop: some-other-accountant
+ maildrop: this, that, theother
+
+ * If you use an LDAP map for lookups other than aliases, you may have to make
+ sure the lookup makes sense. In the case of virtual lookups, maildrops
+ other than mail addresses are pretty useless, because Postfix can't know
+ how to set the ownership for program or file delivery. Your qquueerryy__ffiilltteerr
+ should probably look something like this:
+
+ query_filter = (&(mailacceptinggeneralid=%s)(!(|(maildrop="*|*")
+ (maildrop="*:*")(maildrop="*/*"))))
+
+ * And for that matter, even for aliases, you may not want users to be able to
+ specify their maildrops as programs, includes, etc. This might be
+ particularly pertinent on a "sealed" server where they don't have local
+ UNIX accounts, but exist only in LDAP and Cyrus. You might allow the fun
+ stuff only for directory entries owned by an administrative account, so
+ that if the object had a program as its maildrop and weren't owned by
+ "cn=root" it wouldn't be returned as a valid local user. This will require
+ some thought on your part to implement safely, considering the
+ ramifications of this type of delivery. You may decide it's not worth the
+ bother to allow any of that nonsense in LDAP lookups, ban it in the
+ qquueerryy__ffiilltteerr, and keep things like majordomo lists in local alias
+ databases.
+
+ query_filter = (&(mailacceptinggeneralid=%s)(!(|(maildrop="*|*")
+ (maildrop="*:*")(maildrop="*/*"))(owner=cn=root, dc=your, dc=com)))
+
+ * LDAP lookups are slower than local DB or DBM lookups. For most sites they
+ won't be a bottleneck, but it's a good idea to know how to tune your
+ directory service.
+
+ * Multiple LDAP maps share the same LDAP connection if they differ only in
+ their query related parameters: base, scope, query_filter, and so on. To
+ take advantage of this, avoid spurious differences in the definitions of
+ LDAP maps: host selection order, version, bind, tls parameters, ... should
+ be the same for multiple maps whenever possible.
+
+FFeeeeddbbaacckk
+
+If you have questions, send them to postfix-users@postfix.org. Please include
+relevant information about your Postfix setup: LDAP-related output from
+postconf, which LDAP libraries you built with, and which directory server
+you're using. If your question involves your directory contents, please include
+the applicable bits of some directory entries.
+
+CCrreeddiittss
+
+ * Manuel Guesdon: Spotted a bug with the timeout attribute.
+ * John Hensley: Multiple LDAP sources with more configurable attributes.
+ * Carsten Hoeger: Search scope handling.
+ * LaMont Jones: Domain restriction, URL and DN searches, multiple result
+ attributes.
+ * Mike Mattice: Alias dereferencing control.
+ * Hery Rakotoarisoa: Patches for LDAPv3 updating.
+ * Prabhat K Singh: Wrote the initial Postfix LDAP lookups and connection
+ caching.
+ * Keith Stevenson: RFC 2254 escaping in queries.
+ * Samuel Tardieu: Noticed that searches could include wildcards, prompting
+ the work on RFC 2254 escaping in queries. Spotted a bug in binding.
+ * Sami Haahtinen: Referral chasing and v3 support.
+ * Victor Duchovni: ldap_bind() timeout. With fixes from LaMont Jones:
+ OpenLDAP cache deprecation. Limits on recursion, expansion and search
+ results size. LDAP connection sharing for maps differing only in the query
+ parameters.
+ * Liviu Daia: Support for SSL/STARTTLS. Support for storing map definitions
+ in external files (ldap:/path/ldap.cf) needed to securely store passwords
+ for plain auth.
+ * Liviu Daia revised the configuration interface and added the main.cf
+ configuration feature.
+ * Liviu Daia with further refinements from Jose Luis Tallon and Victor
+ Duchovni developed the common query, result_format, domain and
+ expansion_limit interface for LDAP, MySQL and PosgreSQL.
+ * Gunnar Wrobel provided a first implementation of a feature to limit LDAP
+ search results to leaf nodes only. Victor generalized this into the Postfix
+ 2.4 "leaf_result_attribute" feature.
+ * Quanah Gibson-Mount contributed support for advanced LDAP SASL mechanisms,
+ beyond the password-based LDAP "simple" bind.
+
+And of course Wietse.
+