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