xref: /netbsd-src/external/ibm-public/postfix/dist/html/LDAP_README.html (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
2        "http://www.w3.org/TR/html4/loose.dtd">
3
4<html>
5
6<head>
7
8<title>Postfix LDAP Howto</title>
9
10<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
11
12</head>
13
14<body>
15
16<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix LDAP Howto</h1>
17
18<hr>
19
20<h2>LDAP Support in Postfix</h2>
21
22<p> Postfix can use an LDAP directory as a source for any of its
23lookups:  <a href="aliases.5.html">aliases(5)</a>, <a href="virtual.5.html">virtual(5)</a>, <a href="canonical.5.html">canonical(5)</a>, etc. This allows
24you to keep information for your mail service in a replicated
25network database with fine-grained access controls. By not storing
26it locally on the mail server, the administrators can maintain it
27from anywhere, and the users can control whatever bits of it you
28think appropriate.  You can have multiple mail servers using the
29same information, without the hassle and delay of having to copy
30it to each. </p>
31
32<p> Topics covered in this document:</p>
33
34<ul>
35
36<li><a href="#build">Building Postfix with LDAP support</a>
37
38<li><a href="#config">Configuring LDAP lookups</a>
39
40<li><a href="#example_alias">Example: aliases</a>
41
42<li><a href="#example_virtual">Example: virtual domains/addresses</a>
43
44<li><a href="#example_group">Example: expanding LDAP groups</a>
45
46<li><a href="#other">Other uses of LDAP lookups</a>
47
48<li><a href="#hmmmm">Notes and things to think about</a>
49
50<li><a href="#feedback">Feedback</a>
51
52<li><a href="#credits">Credits</a>
53
54</ul>
55
56<h2><a name="build">Building Postfix with LDAP support</a></h2>
57
58<p> These instructions assume that you build Postfix from source
59code as described in the <a href="INSTALL.html">INSTALL</a> document. Some modification may
60be required if you build Postfix from a vendor-specific source
61package.  </p>
62
63<p> Note 1: Postfix no longer supports the LDAP version 1 interface.
64</p>
65
66<p> Note 2: to use LDAP with Debian GNU/Linux's Postfix, all you
67need is to install the postfix-ldap package and you're done.  There
68is no need to recompile Postfix. </p>
69
70<p> You need to have LDAP libraries and include files installed
71somewhere on your system, and you need to configure the Postfix
72Makefiles accordingly. </p>
73
74<p> For example, to build the OpenLDAP libraries for use with
75Postfix (i.e.  LDAP client code only), you could use the following
76command: </p>
77
78<blockquote>
79<pre>
80% ./configure  --without-kerberos --without-cyrus-sasl --without-tls \
81    --without-threads --disable-slapd --disable-slurpd \
82    --disable-debug --disable-shared
83</pre>
84</blockquote>
85
86<p> If you're using the libraries from the UM distribution
87(<a href="http://www.umich.edu/~dirsvcs/ldap/ldap.html">http://www.umich.edu/~dirsvcs/ldap/ldap.html</a>) or OpenLDAP
88(<a href="http://www.openldap.org">http://www.openldap.org</a>), something like this in the top level of
89your Postfix source tree should work: </p>
90
91<blockquote>
92<pre>
93% make tidy
94% make makefiles CCARGS="-I/usr/local/include -DHAS_LDAP" \
95    <a href="LDAP_README.html">AUXLIBS_LDAP</a>="-L/usr/local/lib -lldap -L/usr/local/lib -llber"
96</pre>
97</blockquote>
98
99<p> Postfix versions before 3.0 use AUXLIBS instead of <a href="LDAP_README.html">AUXLIBS_LDAP</a>.
100With Postfix 3.0 and later, the old AUXLIBS variable still supports
101building a statically-loaded LDAP database client, but only the new
102<a href="LDAP_README.html">AUXLIBS_LDAP</a> variable supports building a dynamically-loaded or
103statically-loaded LDAP database client.  </p>
104
105<blockquote>
106
107<p> Failure to use the <a href="LDAP_README.html">AUXLIBS_LDAP</a> variable will defeat the purpose
108of dynamic database client loading. Every Postfix executable file
109will have LDAP database library dependencies. And that was exactly
110what dynamic database client loading was meant to avoid. </p>
111
112</blockquote>
113
114<p> On Solaris 2.x you may have to specify run-time link information,
115otherwise ld.so will not find some of the shared libraries: </p>
116
117<blockquote>
118<pre>
119% make tidy
120% make makefiles CCARGS="-I/usr/local/include -DHAS_LDAP" \
121    <a href="LDAP_README.html">AUXLIBS_LDAP</a>="-L/usr/local/lib -R/usr/local/lib -lldap \
122            -L/usr/local/lib -R/usr/local/lib -llber"
123</pre>
124</blockquote>
125
126<p> The 'make tidy' command is needed only if you have previously
127built Postfix without LDAP support. </p>
128
129<p> Instead of '/usr/local' specify the actual locations of your
130LDAP include files and libraries. Be sure to not mix LDAP include
131files and LDAP libraries of different versions!! </p>
132
133<p> If your LDAP libraries were built with Kerberos support, you'll
134also need to include your Kerberos libraries in this line. Note
135that the KTH Kerberos IV libraries might conflict with Postfix's
136lib/libdns.a, which defines dns_lookup. If that happens, you'll
137probably want to link with LDAP libraries that lack Kerberos support
138just to build Postfix, as it doesn't support Kerberos binds to the
139LDAP server anyway. Sorry about the bother. </p>
140
141<p> If you're using one of the Netscape LDAP SDKs, you'll need to
142change the AUXLIBS line to point to libldap10.so or libldapssl30.so
143or whatever you have, and you may need to use the appropriate linker
144option (e.g. '-R') so the executables can find it at runtime. </p>
145
146<p> If you are using OpenLDAP, and the libraries were built with SASL
147support, you can add -DUSE_LDAP_SASL to the CCARGS to enable SASL support.
148For example: </p>
149
150<blockquote>
151<pre>
152     CCARGS="-I/usr/local/include -DHAS_LDAP -DUSE_LDAP_SASL"
153</pre>
154</blockquote>
155
156<h2><a name="config">Configuring LDAP lookups</a></h2>
157
158<p> In order to use LDAP lookups, define an LDAP source
159as a table lookup in <a href="postconf.5.html">main.cf</a>, for example: </p>
160
161<blockquote>
162<pre>
163<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/aliases, <a href="ldap_table.5.html">ldap</a>:/etc/postfix/ldap-aliases.cf
164</pre>
165</blockquote>
166
167<p> The file /etc/postfix/ldap-aliases.cf can specify a great number
168of parameters, including parameters that enable LDAP SSL or STARTTLS,
169and LDAP SASL. For a complete description, see the <a href="ldap_table.5.html">ldap_table(5)</a>
170manual page. </p>
171
172<h2><a name="example_alias">Example: local(8) aliases</a></h2>
173
174<p> Here's a basic example for using LDAP to look up <a href="local.8.html">local(8)</a>
175aliases. Assume that in <a href="postconf.5.html">main.cf</a>, you have: </p>
176
177<blockquote>
178<pre>
179<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/aliases, <a href="ldap_table.5.html">ldap</a>:/etc/postfix/ldap-aliases.cf
180</pre>
181</blockquote>
182
183<p> and in <a href="ldap_table.5.html">ldap</a>:/etc/postfix/ldap-aliases.cf you have: </p>
184
185<blockquote>
186<pre>
187server_host = ldap.example.com
188search_base = dc=example, dc=com
189</pre>
190</blockquote>
191
192<p> Upon receiving mail for a local address "ldapuser" that isn't
193found in the /etc/aliases database, Postfix will search the LDAP
194server listening at port 389 on ldap.example.com. It will bind anonymously,
195search for any directory entries whose mailacceptinggeneralid
196attribute is "ldapuser", read the "maildrop" attributes of those
197found, and build a list of their maildrops, which will be treated
198as <a href="http://tools.ietf.org/html/rfc822">RFC822</a> addresses to which the message will be delivered. </p>
199
200<h2><a name="example_virtual">Example: virtual domains/addresses</a></h2>
201
202<p> If you want to keep information for virtual lookups in your
203directory, it's only a little more complicated. First, you need to
204make sure Postfix knows about the virtual domain. An easy way to
205do that is to add the domain to the mailacceptinggeneralid attribute
206of some entry in the directory. Next, you'll want to make sure all
207of your virtual recipient's mailacceptinggeneralid attributes are
208fully qualified with their virtual domains. Finally, if you want
209to designate a directory entry as the default user for a virtual
210domain, just give it an additional mailacceptinggeneralid (or the
211equivalent in your directory) of "@fake.dom". That's right, no
212user part. If you don't want a catchall user, omit this step and
213mail to unknown users in the domain will simply bounce. </p>
214
215<p> In summary, you might have a catchall user for a virtual domain
216that looks like this: </p>
217
218<blockquote>
219<pre>
220     dn: cn=defaultrecipient, dc=fake, dc=dom
221     objectclass: top
222     objectclass: virtualaccount
223     cn: defaultrecipient
224     owner: uid=root, dc=someserver, dc=isp, dc=dom
2251 -&gt; mailacceptinggeneralid: fake.dom
2262 -&gt; mailacceptinggeneralid: @fake.dom
2273 -&gt; maildrop: realuser@real.dom
228</pre>
229</blockquote>
230
231<dl compact>
232
233<dd> <p> 1: Postfix knows fake.dom is a valid virtual domain when
234it looks for this and gets something (the maildrop) back. </p>
235
236<dd> <p> 2: This causes any mail for unknown users in fake.dom to
237go to this entry ... </p>
238
239<dd> <p> 3: ... and then to its maildrop. </p>
240
241</dl>
242
243<p> Normal users might simply have one mailacceptinggeneralid and
244<a href="QSHAPE_README.html#maildrop_queue">maildrop</a>, e.g. "normaluser@fake.dom" and "normaluser@real.dom".
245</p>
246
247<h2><a name="example_group">Example: expanding LDAP groups</a></h2>
248
249<p>
250LDAP is frequently used to store group member information.  There are a
251number of ways of handling LDAP groups.  We will show a few examples in
252order of increasing complexity, but owing to the number of independent
253variables, we can only present a tiny portion of the solution space.
254We show how to:
255</p>
256
257<ol>
258
259<li> <p> query groups as lists of addresses; </p>
260
261<li> <p> query groups as lists of user objects containing addresses; </p>
262
263<li> <p> forward special lists unexpanded to a separate list server,
264for moderation or other processing; </p>
265
266<li> <p> handle complex schemas by controlling expansion and by treating
267leaf nodes specially, using features that are new in Postfix 2.4. </p>
268
269</ol>
270
271<p>
272The example LDAP entries and implied schema below show two group entries
273("agroup" and "bgroup") and four user entries ("auser", "buser", "cuser"
274and "duser"). The group "agroup" has the users "auser" (1) and "buser" (2)
275as members via DN references in the multi-valued attribute "memberdn", and
276direct email addresses of two external users "auser@example.org" (3) and
277"buser@example.org" (4) stored in the multi-valued attribute "memberaddr".
278The same is true of "bgroup" and "cuser"/"duser" (6)/(7)/(8)/(9), but
279"bgroup" also has a "maildrop" attribute of "bgroup@mlm.example.com"
280(5): </p>
281
282<blockquote>
283<pre>
284     dn: cn=agroup, dc=example, dc=com
285     objectclass: top
286     objectclass: ldapgroup
287     cn: agroup
288     mail: agroup@example.com
2891 -&gt; memberdn: uid=auser, dc=example, dc=com
2902 -&gt; memberdn: uid=buser, dc=example, dc=com
2913 -&gt; memberaddr: auser@example.org
2924 -&gt; memberaddr: buser@example.org
293</pre>
294<br>
295
296<pre>
297     dn: cn=bgroup, dc=example, dc=com
298     objectclass: top
299     objectclass: ldapgroup
300     cn: bgroup
301     mail: bgroup@example.com
3025 -&gt; maildrop: bgroup@mlm.example.com
3036 -&gt; memberdn: uid=cuser, dc=example, dc=com
3047 -&gt; memberdn: uid=duser, dc=example, dc=com
3058 -&gt; memberaddr: cuser@example.org
3069 -&gt; memberaddr: duser@example.org
307</pre>
308<br>
309
310<pre>
311     dn: uid=auser, dc=example, dc=com
312     objectclass: top
313     objectclass: ldapuser
314     uid: auser
31510 -&gt; mail: auser@example.com
31611 -&gt; maildrop: auser@mailhub.example.com
317</pre>
318<br>
319
320<pre>
321     dn: uid=buser, dc=example, dc=com
322     objectclass: top
323     objectclass: ldapuser
324     uid: buser
32512 -&gt; mail: buser@example.com
32613 -&gt; maildrop: buser@mailhub.example.com
327</pre>
328<br>
329
330<pre>
331     dn: uid=cuser, dc=example, dc=com
332     objectclass: top
333     objectclass: ldapuser
334     uid: cuser
33514 -&gt; mail: cuser@example.com
336</pre>
337<br>
338
339<pre>
340     dn: uid=duser, dc=example, dc=com
341     objectclass: top
342     objectclass: ldapuser
343     uid: duser
34415 -&gt; mail: duser@example.com
345</pre>
346<br>
347
348</blockquote>
349
350<p> Our first use case ignores the "memberdn" attributes, and assumes
351that groups hold only direct "memberaddr" strings as in (3), (4), (8) and
352(9). The goal is to map the group address to the list of constituent
353"memberaddr" values. This is simple, ignoring the various connection
354related settings (hosts, ports, bind settings, timeouts, ...) we have:
355</p>
356
357<blockquote>
358<pre>
359    simple.cf:
360        ...
361        search_base = dc=example, dc=com
362        query_filter = mail=%s
363        result_attribute = memberaddr
364    $ postmap -q agroup@example.com <a href="ldap_table.5.html">ldap</a>:/etc/postfix/simple.cf \
365        auser@example.org,buser@example.org
366</pre>
367</blockquote>
368
369<p> We search "dc=example, dc=com". The "mail" attribute is used in the
370query_filter to locate the right group, the "result_attribute" setting
371described in <a href="ldap_table.5.html">ldap_table(5)</a> is used to specify that "memberaddr" values
372from the matching group are to be returned as a comma separated list.
373Always check tables using <a href="postmap.1.html">postmap(1)</a> with the "-q" option, before
374deploying them into production use in <a href="postconf.5.html">main.cf</a>. </p>
375
376<p> Our second use case instead expands "memberdn" attributes (1), (2),
377(6) and (7), follows the DN references and returns the "maildrop" of the
378referenced user entries. Here we use the "special_result_attribute"
379setting from <a href="ldap_table.5.html">ldap_table(5)</a> to designate the "memberdn" attribute
380as holding DNs of the desired member entries. The "result_attribute"
381setting selects which attributes are returned from the selected DNs. It
382is important to choose a result attribute that is not also present in
383the group object, because result attributes are collected from both
384the group and the member DNs. In this case we choose "maildrop" and
385assume for the moment that groups never have a "maildrop" (the "bgroup"
386"maildrop" attribute is for a different use case). The returned data for
387"auser" and "buser" is from items (11) and (13) in the example data. </p>
388
389<blockquote>
390<pre>
391    special.cf:
392        ...
393        search_base = dc=example, dc=com
394        query_filter = mail=%s
395        result_attribute = maildrop
396        special_result_attribute = memberdn
397    $ postmap -q agroup@example.com <a href="ldap_table.5.html">ldap</a>:/etc/postfix/special.cf \
398        auser@mailhub.example.com,buser@mailhub.example.com
399</pre>
400</blockquote>
401
402<p> Note: if the desired member object result attribute is always also
403present in the group, you get surprising results: the expansion also
404returns the address of the group. This is a known limitation of Postfix
405releases prior to 2.4, and is addressed in the new with Postfix 2.4
406"leaf_result_attribute" feature described in <a href="ldap_table.5.html">ldap_table(5)</a>. </p>
407
408<p> Our third use case has some groups that are expanded immediately,
409and other groups that are forwarded to a dedicated mailing list manager
410host for delayed expansion. This uses two LDAP tables, one for users
411and forwarded groups and a second for groups that can be expanded
412immediately. It is assumed that groups that require forwarding are
413never nested members of groups that are directly expanded. </p>
414
415<blockquote>
416<pre>
417    no_expand.cf:
418        ...
419        search_base = dc=example, dc=com
420        query_filter = mail=%s
421        result_attribute = maildrop
422    expand.cf
423        ...
424        search_base = dc=example, dc=com
425        query_filter = mail=%s
426        result_attribute = maildrop
427        special_result_attribute = memberdn
428    $ postmap -q auser@example.com \
429        <a href="ldap_table.5.html">ldap</a>:/etc/postfix/no_expand.cf <a href="ldap_table.5.html">ldap</a>:/etc/postfix/expand.cf \
430        auser@mailhub.example.com
431    $ postmap -q agroup@example.com \
432        <a href="ldap_table.5.html">ldap</a>:/etc/postfix/no_expand.cf <a href="ldap_table.5.html">ldap</a>:/etc/postfix/expand.cf \
433        auser@mailhub.example.com,buser@mailhub.example.com
434    $ postmap -q bgroup@example.com \
435        <a href="ldap_table.5.html">ldap</a>:/etc/postfix/no_expand.cf <a href="ldap_table.5.html">ldap</a>:/etc/postfix/expand.cf \
436        bgroup@mlm.example.com
437</pre>
438</blockquote>
439
440<p> Non-group objects and groups with delayed expansion (those that have a
441maildrop attribute) are rewritten to a single maildrop value. Groups that
442don't have a maildrop are expanded as the second use case. This admits
443a more elegant solution with Postfix 2.4 and later. </p>
444
445<p> Our final use case is the same as the third, but this time uses new
446features in Postfix 2.4. We now are able to use just one LDAP table and
447no longer need to assume that forwarded groups are never nested inside
448expanded groups. </p>
449
450<blockquote>
451<pre>
452    fancy.cf:
453        ...
454        search_base = dc=example, dc=com
455        query_filter = mail=%s
456        result_attribute = memberaddr
457        special_result_attribute = memberdn
458        terminal_result_attribute = maildrop
459        leaf_result_attribute = mail
460    $ postmap -q auser@example.com <a href="ldap_table.5.html">ldap</a>:/etc/postfix/fancy.cf \
461        auser@mailhub.example.com
462    $ postmap -q cuser@example.com <a href="ldap_table.5.html">ldap</a>:/etc/postfix/fancy.cf \
463        cuser@example.com
464    $ postmap -q agroup@example.com <a href="ldap_table.5.html">ldap</a>:/etc/postfix/fancy.cf \
465        auser@mailhub.example.com,buser@mailhub.example.com,auser@example.org,buser@example.org
466    $ postmap -q bgroup@example.com <a href="ldap_table.5.html">ldap</a>:/etc/postfix/fancy.cf \
467        bgroup@mlm.example.com
468</pre>
469</blockquote>
470
471<p> Above, delayed expansion is enabled via "terminal_result_attribute",
472which, if present, is used as the sole result and all other expansion is
473suppressed. Otherwise, the "leaf_result_attribute" is only returned for
474leaf objects that don't have a "special_result_attribute" (non-groups),
475while the "result_attribute" (direct member address of groups) is returned
476at every level of recursive expansion, not just the leaf nodes. This fancy
477example illustrates all the features of Postfix 2.4 group expansion. </p>
478
479<h2><a name="other">Other uses of LDAP lookups</a></h2>
480
481Other common uses for LDAP lookups include rewriting senders and
482recipients with Postfix's canonical lookups, for example in order
483to make mail leaving your site appear to be coming from
484"First.Last@example.com" instead of "userid@example.com".
485
486<h2><a name="hmmmm">Notes and things to think about</a></h2>
487
488<ul>
489
490<li> <p> The bits of schema and attribute names used in this document are just
491  examples. There's nothing special about them, other than that some are
492  the defaults in the LDAP configuration parameters. You can use
493  whatever schema you like, and configure Postfix accordingly. </p>
494
495<li> <p> You probably want to make sure that mailacceptinggeneralids are
496  unique, and that not just anyone can specify theirs as postmaster or
497  root, say. </p>
498
499<li> <p> An entry can have an arbitrary number of mailacceptinggeneralids or
500  maildrops. Maildrops can also be comma-separated lists of addresses.
501  They will all be found and returned by the lookups. For example, you
502  could define an entry intended for use as a mailing list that looks
503  like this (Warning! Schema made up just for this example): </p>
504
505<blockquote>
506<pre>
507dn: cn=Accounting Staff List, dc=example, dc=com
508cn: Accounting Staff List
509o: example.com
510objectclass: maillist
511mailacceptinggeneralid: accountingstaff
512mailacceptinggeneralid: accounting-staff
513maildrop: mylist-owner
514maildrop: an-accountant
515maildrop: some-other-accountant
516maildrop: this, that, theother
517</pre>
518</blockquote>
519
520<li> <p> If you use an LDAP map for lookups other than aliases, you may have to
521  make sure the lookup makes sense. In the case of virtual lookups,
522  maildrops other than mail addresses are pretty useless, because
523  Postfix can't know how to set the ownership for program or file
524  delivery. Your <b>query_filter</b> should probably look something like this: </p>
525
526<blockquote>
527<pre>
528query_filter = (&amp;(mailacceptinggeneralid=%s)(!(|(maildrop="*|*")(maildrop="*:*")(maildrop="*/*"))))
529</pre>
530</blockquote>
531
532<li> <p> And for that matter, even for aliases, you may not want users able to
533  specify their maildrops as programs, includes, etc. This might be
534  particularly pertinent on a "sealed" server where they don't have
535  local UNIX accounts, but exist only in LDAP and Cyrus. You might allow
536  the fun stuff only for directory entries owned by an administrative
537  account,
538  so that if the object had a program as its maildrop and weren't owned
539  by "cn=root" it wouldn't be returned as a valid local user. This will
540  require some thought on your part to implement safely, considering the
541  ramifications of this type of delivery. You may decide it's not worth
542  the bother to allow any of that nonsense in LDAP lookups, ban it in
543  the <b>query_filter</b>, and keep things like majordomo lists in local alias
544  databases. </p>
545
546<blockquote>
547<pre>
548query_filter = (&amp;(mailacceptinggeneralid=%s)(!(|(maildrop="*|*")(maildrop="*:*")(maildrop="*/*"))(owner=cn=root, dc=your, dc=com)))
549</pre>
550</blockquote>
551
552<li> <p> LDAP lookups are slower than local DB or DBM lookups. For most sites
553  they won't be a bottleneck, but it's a good idea to know how to tune
554  your directory service. </p>
555
556<li> <p> Multiple LDAP maps share the same LDAP connection if they differ
557  only in their query related parameters: base, scope, query_filter, and
558  so on. To take advantage of this, avoid spurious differences in the
559  definitions of LDAP maps: host selection order, version, bind, tls
560  parameters, ... should be the same for multiple maps whenever possible. </p>
561
562</ul>
563
564<h2><a name="feedback">Feedback</a></h2>
565
566<p> If you have questions, send them to postfix-users@postfix.org. Please
567include relevant information about your Postfix setup: LDAP-related
568output from postconf, which LDAP libraries you built with, and which
569directory server you're using. If your question involves your directory
570contents, please include the applicable bits of some directory entries. </p>
571
572<h2><a name="credits">Credits</a></h2>
573
574<ul>
575
576<li>Manuel Guesdon: Spotted a bug with the timeout attribute.
577
578<li>John Hensley: Multiple LDAP sources with more configurable attributes.
579
580<li>Carsten Hoeger: Search scope handling.
581
582<li>LaMont Jones: Domain restriction, URL and DN searches, multiple result
583              attributes.
584
585<li>Mike Mattice: Alias dereferencing control.
586
587<li>Hery Rakotoarisoa: Patches for LDAPv3 updating.
588
589<li>Prabhat K Singh: Wrote the initial Postfix LDAP lookups and connection caching.
590
591<li>Keith Stevenson: <a href="http://tools.ietf.org/html/rfc2254">RFC 2254</a> escaping in queries.
592
593<li>Samuel Tardieu: Noticed that searches could include wildcards, prompting
594                the work on <a href="http://tools.ietf.org/html/rfc2254">RFC 2254</a> escaping in queries. Spotted a bug
595                in binding.
596
597<li>Sami Haahtinen: Referral chasing and v3 support.
598
599<li>Victor Duchovni: ldap_bind() timeout. With fixes from LaMont Jones:
600                 OpenLDAP cache deprecation. Limits on recursion, expansion
601                 and search results size. LDAP connection sharing for maps
602                 differing only in the query parameters.
603
604<li>Liviu Daia: Support for SSL/STARTTLS. Support for storing map definitions in
605            external files (<a href="ldap_table.5.html">ldap</a>:/path/ldap.cf) needed to securely store
606            passwords for plain auth.
607
608<li>Liviu Daia revised the configuration interface and added the <a href="postconf.5.html">main.cf</a>
609    configuration feature.</li>
610
611<li>Liviu Daia with further refinements from Jose Luis Tallon and
612Victor Duchovni developed the common query, result_format, domain and
613expansion_limit interface for LDAP, MySQL and PosgreSQL.</li>
614
615<li>Gunnar Wrobel provided a first implementation of a feature to
616limit LDAP search results to leaf nodes only. Victor generalized
617this into the Postfix 2.4 "leaf_result_attribute" feature. </li>
618
619<li>Quanah Gibson-Mount contributed support for advanced LDAP SASL
620mechanisms, beyond the password-based LDAP "simple" bind. </li>
621
622</ul>
623
624And of course Wietse.
625
626</body>
627
628</html>
629