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 -> mailacceptinggeneralid: fake.dom 2262 -> mailacceptinggeneralid: @fake.dom 2273 -> 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 -> memberdn: uid=auser, dc=example, dc=com 2902 -> memberdn: uid=buser, dc=example, dc=com 2913 -> memberaddr: auser@example.org 2924 -> 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 -> maildrop: bgroup@mlm.example.com 3036 -> memberdn: uid=cuser, dc=example, dc=com 3047 -> memberdn: uid=duser, dc=example, dc=com 3058 -> memberaddr: cuser@example.org 3069 -> 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 -> mail: auser@example.com 31611 -> 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 -> mail: buser@example.com 32613 -> 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 -> 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 -> 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 = (&(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 = (&(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