-TCRYPTO_EX_DATA
-TCTABLE
-TCTABLE_ENTRY
--TXSASL_CYRUS_CLIENT
--TXSASL_CYRUS_ERROR_INFO
--TXSASL_CYRUS_SERVER
-TDELIVER_ATTR
-TDELIVER_REQUEST
-TDELTA_TIME
-TXSASL_CLIENT
-TXSASL_CLIENT_IMPL
-TXSASL_CLIENT_IMPL_INFO
+-TXSASL_CYRUS_CLIENT
+-TXSASL_CYRUS_ERROR_INFO
+-TXSASL_CYRUS_SERVER
+-TXSASL_DOVECOT_SERVER
+-TXSASL_DOVECOT_SERVER_IMPL
-TXSASL_SERVER
-TXSASL_SERVER_IMPL
-TXSASL_SERVER_IMPL_INFO
user" errors by "authentication failed" errors. File:
xsasl/xsasl_cyrus_server.c.
-Open problems:
+ Safety: the Postfix SMTP client no longer uses CNAME expanded
+ hostnames for logging, SASL password lookup, TLS policy
+ decisions, or TLS certificate verification. Instead it
+ uses the name of the recipient domain, or the host or domain
+ name specified in Postfix configuration files. Of course
+ this won't prevent cheating with hostnames that appear in
+ MX lookup results. To avoid that you will have to suppress
+ MX lookups with explicit [hostname] entries in transport
+ maps. Files: dns/dns_lookup.c, dns/dns_rr.c.
+
+20051222
+
+ Feature: Dovecot SASL authentication (server side) plug-in
+ by Timo Sirainen. This builds without external library
+ dependencies and is therefore compiled in by default.
+ Files: xsasl/xsasl_dovecot_server.[hc].
+
+ Safety: set the default LANG=C, instead of deleting LANG
+ from the environment and assuming the right thing will
+ happen. File: global/mail_params.h.
+
+ Safety: always add the ISASCII() requirement to the ISXXX()
+ macros, because they are used for protocol and policy
+ enforcement. File: util/sys_defs.h.
+
+ Bugfix: null pointer in the 20051219 policy delegation
+ crypto attributes. File: smtpd/smtpd_check.c.
+
+ Compatibility: "resolve_numeric_domain = yes" will accept
+ addresses with numeric domains instead of rejecting them as
+ invalid. Files: trivial-rewrite/resolve.c, util/vstring.c.
- Reject numeric domains only when strict envelope syntax is
- turned on.
+Open problems:
"postsuper -r" no longer resets the message arrival time,
because pickup(8) no longer overrides queue file time stamp
This document covers the following topics:
* What SASL versions are supported
+ * Building Postfix with Dovecot SASL support
* Building the Cyrus SASL library
* Building Postfix with Cyrus SASL support
* Enabling SASL authentication in the Postfix SMTP server
+ * Dovecot SASL configuration for the Postfix SMTP server
+ * Cyrus SASL configuration for the Postfix SMTP server
* Testing SASL authentication in the Postfix SMTP server
* Trouble shooting the SASL internals
* Enabling SASL authentication in the Postfix SMTP client
W\bWh\bha\bat\bt S\bSA\bAS\bSL\bL v\bve\ber\brs\bsi\bio\bon\bns\bs a\bar\bre\be s\bsu\bup\bpp\bpo\bor\brt\bte\bed\bd
-This document describes Postfix with Cyrus SASL version 1 and Cyrus SASL
-version 2. Postfix version 2.3 introduces has a plug-in mechanism for other
-SASL implementations. Support for other implementations is currently not part
-of the Postfix distribution and will be described elsewhere.
+This document describes Postfix with the following SASL implementations:
+
+ * Cyrus SASL version 1 (client and server).
+
+ * Cyrus SASL version 2 (client and server).
+
+ * Dovecot protocol version 1 (server only, Postfix version 2.3 and later)
+
+Postfix version 2.3 introduces a plug-in mechanism that provides support for
+multiple SASL implementations. To find out what implementations are built into
+Postfix, use the following commands:
+
+ % postconf -a (SASL support in the SMTP server)
+ % postconf -A (SASL support in the SMTP+LMTP client)
+
+Needless to say, these commands are not available in Postfix versions before
+2.3.
+
+B\bBu\bui\bil\bld\bdi\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx w\bwi\bit\bth\bh D\bDo\bov\bve\bec\bco\bot\bt S\bSA\bAS\bSL\bL s\bsu\bup\bpp\bpo\bor\brt\bt
+
+Dovecot is available via http://www.dovecot.org/. It uses its own daemon
+process for authentication. Building Postfix with Dovecot SASL support is
+relatively easy, because there is no need to link extra libraries into Postfix.
+
+To generate the necessary Makefiles, execute the following in the Postfix top-
+level directory:
+
+% make makefiles CCARGS='-DUSE_SASL_AUTH -DDEF_SASL_SERVER=\"dovecot\"'
+
+Notes:
+
+ * The "-DDEF_SASL_SERVER" stuff is not necessary; it just makes Postfix
+ configuration a little more convenient because you don't have to specify
+ the SASL plug-in type in the Postfix main.cf file.
+
+ * If you also want support for LDAP or TLS, you will have to merge their
+ CCARGS and AUXLIBS into the above command line.
+
+ * After this, proceed with "make" as described in the INSTALL document.
B\bBu\bui\bil\bld\bdi\bin\bng\bg t\bth\bhe\be C\bCy\byr\bru\bus\bs S\bSA\bAS\bSL\bL l\bli\bib\bbr\bra\bar\bry\by
Note: the SASL login names will be shared with the entire world.
+D\bDo\bov\bve\bec\bco\bot\bt S\bSA\bAS\bSL\bL c\bco\bon\bnf\bfi\big\bgu\bur\bra\bat\bti\bio\bon\bn f\bfo\bor\br t\bth\bhe\be P\bPo\bos\bst\btf\bfi\bix\bx S\bSM\bMT\bTP\bP s\bse\ber\brv\bve\ber\br
+
+On the Postfix side you need to specify the location of the Dovecot
+authentication daemon socket. We use a pathname relative to the Postfix queue
+directory, so that it will work whether or not Postfix runs chrooted:
+
+ /etc/postfix/main.cf:
+ smtpd_sasl_type = dovecot
+ smtpd_sasl_path = private/auth
+
+On the Dovecot side you also need to specify the Dovecot authentication daemon
+socket. In this case we specify an absolute pathname. In the example we assume
+that the Postfix queue is under /var/spool/postfix/.
+
+ /some/where/dovecot.conf:
+ auth default {
+ ..
+ socket listen {
+ client {
+ path = /var/spool/postfix/private/auth
+ mode = 0666
+ }
+ }
+ }
+
+See the Dovecot documentation for how to configure the Dovecot authentication
+server.
+
+C\bCy\byr\bru\bus\bs S\bSA\bAS\bSL\bL c\bco\bon\bnf\bfi\big\bgu\bur\bra\bat\bti\bio\bon\bn f\bfo\bor\br t\bth\bhe\be P\bPo\bos\bst\btf\bfi\bix\bx S\bSM\bMT\bTP\bP s\bse\ber\brv\bve\ber\br
+
In /usr/local/lib/sasl/smtpd.conf (Cyrus SASL version 1.5.5) or /usr/local/lib/
sasl2/smtpd.conf (Cyrus SASL version 2.1.1) you need to specify how the server
should validate client passwords.
reject_unauthenticated_sender_login_mismatch, and revised the docs.
* Wietse made another iteration through the code to add plug-in support for
multiple implementations.
+ * The Dovecot plug-in was originally implemented by Timo Sirainen of
+ Procontrol, Finland.
If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2
before proceeding.
+Major changes with snapshot 20051222
+====================================
+
+Dovecot SASL support (SMTP server only). Details can be found
+in the SASL_README document.
+
+You can now use "resolve_numeric_address = yes" to stop Postfix
+from rejecting user@ipaddress as an invalid destination. It will
+deliver the mail to user@[ipaddress] instead.
+
Incompatibility with snapshot 20051220
======================================
<li><a href="#versions">What SASL versions are supported</a>
+<li><a href="#build_dovecot">Building Postfix with Dovecot SASL
+support</a></li>
+
<li><a href="#build_sasl">Building the Cyrus SASL library</a>
<li><a href="#build_postfix">Building Postfix with Cyrus SASL
<li><a href="#server_sasl">Enabling SASL authentication in the
Postfix SMTP server</a></li>
+<li><a href="#server_dovecot">Dovecot SASL configuration for the Postfix
+SMTP server</a></li>
+
+<li><a href="#server_cyrus">Cyrus SASL configuration for the Postfix
+SMTP server</a></li>
+
<li><a href="#server_test">Testing SASL authentication in the
Postfix SMTP server</a></li>
<h2><a name="versions">What SASL versions are supported</a></h2>
-<p> This document describes Postfix with Cyrus SASL version 1 and
-Cyrus SASL version 2. Postfix version 2.3 introduces has a plug-in
-mechanism for other SASL implementations. Support for other
-implementations is currently not part of the Postfix distribution
-and will be described elsewhere. </p>
+<p> This document describes Postfix with the following SASL
+implementations: </p>
+
+<ul>
+
+<li> <p> Cyrus SASL version 1 (client and server). </p>
+
+<li> <p> Cyrus SASL version 2 (client and server). </p>
+
+<li> <p> Dovecot protocol version 1 (server only, Postfix version
+2.3 and later) </p>
+
+</ul>
+
+<p> Postfix version 2.3 introduces a plug-in mechanism that provides
+support for multiple SASL implementations. To find out what
+implementations are built into Postfix, use the following commands:
+</p>
+
+<blockquote>
+<pre>
+% postconf -a (SASL support in the SMTP server)
+% postconf -A (SASL support in the SMTP+LMTP client)
+</pre>
+</blockquote>
+
+<p> Needless to say, these commands are not available in Postfix
+versions before 2.3. </p>
+
+<h2><a name="build_dovecot">Building Postfix with Dovecot SASL
+support</a></h2>
+
+<p> Dovecot is available via <a href="http://www.dovecot.org/">http://www.dovecot.org/</a>. It uses its
+own daemon process for authentication. Building Postfix with Dovecot
+SASL support is relatively easy, because there is no need to link
+extra libraries into Postfix. </p>
+
+<p> To generate the necessary Makefiles, execute the following
+in the Postfix top-level directory: </p>
+
+<pre>
+% make makefiles CCARGS='-DUSE_SASL_AUTH -DDEF_SASL_SERVER=\"dovecot\"'
+</pre>
+
+<p> Notes: </p>
+
+<ul>
+
+<li> <p> The "-DDEF_SASL_SERVER" stuff is not necessary; it just
+makes Postfix configuration a little more convenient because you
+don't have to specify the SASL plug-in type in the Postfix main.cf
+file. </p>
+
+<li> <p> If you also want support for LDAP or TLS, you will have to merge
+their CCARGS and AUXLIBS into the above command line. </p>
+
+<li> <p> After this, proceed with "<tt>make</tt>" as described in the
+<a href="INSTALL.html">INSTALL</a> document. </p>
+
+</ul>
<h2><a name="build_sasl">Building the Cyrus SASL library</a></h2>
<p> Note: the SASL login names will be shared with the entire world.
</p>
+<h2><a name="server_dovecot">Dovecot SASL configuration for the
+Postfix SMTP server</a></h2>
+
+<p> On the Postfix side you need to specify the location of the
+Dovecot authentication daemon socket. We use a pathname relative
+to the Postfix queue directory, so that it will work whether or not
+Postfix runs chrooted: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+ <a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a> = dovecot
+ <a href="postconf.5.html#smtpd_sasl_path">smtpd_sasl_path</a> = private/auth
+</pre>
+</blockquote>
+
+<p> On the Dovecot side you also need to specify the Dovecot
+authentication daemon socket. In this case we specify an
+absolute pathname. In the example we assume that the
+Postfix queue is under /var/spool/postfix/. </p>
+
+<blockquote>
+<pre>
+/some/where/dovecot.conf:
+ auth default {
+ ..
+ socket listen {
+ client {
+ path = /var/spool/postfix/private/auth
+ mode = 0666
+ }
+ }
+ }
+</pre>
+</blockquote>
+
+<p> See the Dovecot documentation for how to configure the Dovecot
+authentication server. </p>
+
+<h2><a name="server_cyrus">Cyrus SASL configuration for the Postfix
+SMTP server</a></h2>
+
<p> In /usr/local/lib/sasl/smtpd.conf (Cyrus SASL version 1.5.5) or
/usr/local/lib/sasl2/smtpd.conf (Cyrus SASL version 2.1.1) you need to
specify how the server should validate client passwords. </p>
<li> Wietse made another iteration through the code to add
plug-in support for multiple implementations.
+<li> The Dovecot plug-in was originally implemented by Timo Sirainen
+of Procontrol, Finland.
+
</ul>
</body>
<b>-a</b> List the available SASL server plug-in types. The
SASL plug-in type is selected with the
- <b><a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a></b> configuration parameter.
+ <b><a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a></b> configuration parameter by specify-
+ ing one of the names listed below.
- This feature is available with Postfix 2.3 and
+ This feature is available with Postfix 2.3 and
later.
- <b>-A</b> List the available SASL client plug-in types. The
- SASL plug-in type is selected with the
- <b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a></b> or <b><a href="postconf.5.html#lmtp_sasl_type">lmtp_sasl_type</a></b> configuration
- parameters.
+ <b>cyrus</b> This server plug-in is available when Post-
+ fix is built with Cyrus SASL support.
+
+ <b>dovecot</b>
+ This server plug-in requires the Dovecot
+ authentication server.
+
+ <b>-A</b> List the available SASL client plug-in types. The
+ SASL plug-in type is selected with the
+ <b><a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a></b> or <b><a href="postconf.5.html#lmtp_sasl_type">lmtp_sasl_type</a></b> configuration
+ parameters by specifying one of the names listed
+ below.
This feature is available with Postfix 2.3 and
later.
+ <b>cyrus</b> This client plug-in is available when Post-
+ fix is built with Cyrus SASL support.
+
<b>-b</b> [<i>template</i><b>_</b><i>file</i>]
Display the message text that appears at the begin-
- ning of delivery status notification (DSN) mes-
- sages, with $<b>name</b> expressions replaced by actual
- values. To override the built-in message text,
- specify a template file at the end of the command
- line, or specify a template file in main.cf with
- the <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter. To force
- selection of the built-in message text templates,
- specify an empty template file name (in shell lan-
+ ning of delivery status notification (DSN) mes-
+ sages, with $<b>name</b> expressions replaced by actual
+ values. To override the built-in message text,
+ specify a template file at the end of the command
+ line, or specify a template file in main.cf with
+ the <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter. To force
+ selection of the built-in message text templates,
+ specify an empty template file name (in shell lan-
guage: "").
- This feature is available with Postfix 2.3 and
+ This feature is available with Postfix 2.3 and
later.
<b>-c</b> <i>config</i><b>_</b><i>dir</i>
- The <b>main.cf</b> configuration file is in the named
+ The <b>main.cf</b> configuration file is in the named
directory instead of the default configuration
directory.
- <b>-d</b> Print default parameter settings instead of actual
+ <b>-d</b> Print default parameter settings instead of actual
settings.
- <b>-e</b> Edit the <b>main.cf</b> configuration file. The file is
+ <b>-e</b> Edit the <b>main.cf</b> configuration file. The file is
copied to a temporary file then renamed into place.
- Parameters and values are specified on the command
- line. Use quotes in order to protect shell
+ Parameters and values are specified on the command
+ line. Use quotes in order to protect shell
metacharacters and whitespace.
- <b>-h</b> Show parameter values only, not the ``name = ''
+ <b>-h</b> Show parameter values only, not the ``name = ''
label that normally precedes the value.
- <b>-l</b> List the names of all supported mailbox locking
+ <b>-l</b> List the names of all supported mailbox locking
methods. Postfix supports the following methods:
- <b>flock</b> A kernel-based advisory locking method for
- local files only. This locking method is
- available on systems with a BSD compatible
+ <b>flock</b> A kernel-based advisory locking method for
+ local files only. This locking method is
+ available on systems with a BSD compatible
library.
- <b>fcntl</b> A kernel-based advisory locking method for
+ <b>fcntl</b> A kernel-based advisory locking method for
local and remote files.
<b>dotlock</b>
- An application-level locking method. An
- application locks a file named <i>filename</i> by
- creating a file named <i>filename</i><b>.lock</b>. The
- application is expected to remove its own
- lock file, as well as stale lock files that
+ An application-level locking method. An
+ application locks a file named <i>filename</i> by
+ creating a file named <i>filename</i><b>.lock</b>. The
+ application is expected to remove its own
+ lock file, as well as stale lock files that
were left behind after abnormal termination.
<b>-m</b> List the names of all supported lookup table types.
- In Postfix configuration files, lookup tables are
- specified as <i>type</i><b>:</b><i>name</i>, where <i>type</i> is one of the
- types listed below. The table <i>name</i> syntax depends
- on the lookup table type as described in the <a href="DATABASE_README.html">DATA</a>-
+ In Postfix configuration files, lookup tables are
+ specified as <i>type</i><b>:</b><i>name</i>, where <i>type</i> is one of the
+ types listed below. The table <i>name</i> syntax depends
+ on the lookup table type as described in the <a href="DATABASE_README.html">DATA</a>-
<a href="DATABASE_README.html">BASE_README</a> document.
- <b>btree</b> A sorted, balanced tree structure. This is
+ <b>btree</b> A sorted, balanced tree structure. This is
available on systems with support for Berke-
ley DB databases.
- <b>cdb</b> A read-optimized structure with no support
- for incremental updates. This is available
+ <b>cdb</b> A read-optimized structure with no support
+ for incremental updates. This is available
on systems with support for CDB databases.
- <b>cidr</b> A table that associates values with Class-
- less Inter-Domain Routing (CIDR) patterns.
+ <b>cidr</b> A table that associates values with Class-
+ less Inter-Domain Routing (CIDR) patterns.
This is described in <a href="cidr_table.5.html"><b>cidr_table</b>(5)</a>.
<b>dbm</b> An indexed file type based on hashing. This
<b>environ</b>
The UNIX process environment array. The
- lookup key is the variable name. Originally
- implemented for testing, someone may find
+ lookup key is the variable name. Originally
+ implemented for testing, someone may find
this useful someday.
<b>hash</b> An indexed file type based on hashing. This
- is available on systems with support for
+ is available on systems with support for
Berkeley DB databases.
<b>ldap</b> (read-only)
- Perform lookups using the LDAP protocol.
+ Perform lookups using the LDAP protocol.
This is described in <a href="ldap_table.5.html"><b>ldap_table</b>(5)</a>.
<b>mysql</b> (read-only)
- Perform lookups using the MYSQL protocol.
+ Perform lookups using the MYSQL protocol.
This is described in <a href="mysql_table.5.html"><b>mysql_table</b>(5)</a>.
<b>pcre</b> (read-only)
A lookup table based on Perl Compatible Reg-
- ular Expressions. The file format is
+ ular Expressions. The file format is
described in <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>.
<b>pgsql</b> (read-only)
- Perform lookups using the PostgreSQL proto-
+ Perform lookups using the PostgreSQL proto-
col. This is described in <a href="pgsql_table.5.html"><b>pgsql_table</b>(5)</a>.
<b>proxy</b> (read-only)
- A lookup table that is implemented via the
- Postfix <a href="proxymap.8.html"><b>proxymap</b>(8)</a> service. The table name
+ A lookup table that is implemented via the
+ Postfix <a href="proxymap.8.html"><b>proxymap</b>(8)</a> service. The table name
syntax is <i>type</i><b>:</b><i>name</i>.
<b>regexp</b> (read-only)
A lookup table based on regular expressions.
- The file format is described in <a href="regexp_table.5.html"><b>regexp_ta-</b></a>
+ The file format is described in <a href="regexp_table.5.html"><b>regexp_ta-</b></a>
<a href="regexp_table.5.html"><b>ble</b>(5)</a>.
<b>sdbm</b> An indexed file type based on hashing. This
- is available on systems with support for
+ is available on systems with support for
SDBM databases.
<b>static</b> (read-only)
- A table that always returns its name as
- lookup result. For example, <b>static:foobar</b>
- always returns the string <b>foobar</b> as lookup
+ A table that always returns its name as
+ lookup result. For example, <b>static:foobar</b>
+ always returns the string <b>foobar</b> as lookup
result.
<b>tcp</b> (read-only)
Perform lookups using a simple request-reply
- protocol that is described in <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>.
- This feature is not included with Postfix
+ protocol that is described in <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>.
+ This feature is not included with Postfix
2.2.
<b>unix</b> (read-only)
- A limited way to query the UNIX authentica-
+ A limited way to query the UNIX authentica-
tion database. The following tables are
implemented:
<b>unix:passwd.byname</b>
- The table is the UNIX password data-
- base. The key is a login name. The
- result is a password file entry in
+ The table is the UNIX password data-
+ base. The key is a login name. The
+ result is a password file entry in
<b>passwd</b>(5) format.
<b>unix:group.byname</b>
The table is the UNIX group database.
- The key is a group name. The result
- is a group file entry in <b>group</b>(5)
+ The key is a group name. The result
+ is a group file entry in <b>group</b>(5)
format.
- Other table types may exist depending on how Post-
+ Other table types may exist depending on how Post-
fix was built.
<b>-n</b> Print parameter settings that are not left at their
<b>-t</b> [<i>template</i><b>_</b><i>file</i>]
Display the templates for delivery status notifica-
- tion (DSN) messages. To override the built-in tem-
- plates, specify a template file at the end of the
+ tion (DSN) messages. To override the built-in tem-
+ plates, specify a template file at the end of the
command line, or specify a template file in main.cf
- with the <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter. To force
- selection of the built-in templates, specify an
+ with the <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter. To force
+ selection of the built-in templates, specify an
empty template file name (in shell language: "").
- This feature is available with Postfix 2.3 and
+ This feature is available with Postfix 2.3 and
later.
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
- tiple <b>-v</b> options make the software increasingly
+ tiple <b>-v</b> options make the software increasingly
verbose.
<b>DIAGNOSTICS</b>
Directory with Postfix configuration files.
<b>CONFIGURATION PARAMETERS</b>
- The following <b>main.cf</b> parameters are especially relevant
+ The following <b>main.cf</b> parameters are especially relevant
to this program.
- The text below provides only a parameter summary. See
+ The text below provides only a parameter summary. See
<a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix main.cf and
+ The default location of the Postfix main.cf and
master.cf configuration files.
<b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a> (empty)</b>
- Pathname of a configuration file with bounce mes-
+ Pathname of a configuration file with bounce mes-
sage templates.
<b>FILES</b>
<a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
that rewrite into a form that ends in the "@" null domain. </p>
+</DD>
+
+<DT><b><a name="resolve_numeric_domain">resolve_numeric_domain</a>
+(default: no)</b></DT><DD>
+
+<p> Resolve "user@ipaddress" as "user@[ipaddress]", instead of
+rejecting the address as invalid. </p>
+
+<p> This feature is available in Postfix 2.3 and later.
+
+
</DD>
<DT><b><a name="rewrite_service_name">rewrite_service_name</a>
as if the local hostname were specified, instead of
rejecting the address as invalid.
+ <b><a href="postconf.5.html#resolve_numeric_domain">resolve_numeric_domain</a> (no)</b>
+ Resolve "user@ipaddress" as "user@[ipaddress]",
+ instead of rejecting the address as invalid.
+
<b>ADDRESS REWRITING CONTROLS</b>
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The domain name that locally-posted mail appears to
- come from, and that locally posted mail is deliv-
+ come from, and that locally posted mail is deliv-
ered to.
<b><a href="postconf.5.html#allow_percent_hack">allow_percent_hack</a> (yes)</b>
- Enable the rewriting of the form "user%domain" to
+ Enable the rewriting of the form "user%domain" to
"user@domain".
<b><a href="postconf.5.html#append_at_myorigin">append_at_myorigin</a> (yes)</b>
- With locally submitted mail, append the string
- "@$<a href="postconf.5.html#myorigin">myorigin</a>" to mail addresses without domain
+ With locally submitted mail, append the string
+ "@$<a href="postconf.5.html#myorigin">myorigin</a>" to mail addresses without domain
information.
<b><a href="postconf.5.html#append_dot_mydomain">append_dot_mydomain</a> (yes)</b>
- With locally submitted mail, append the string
- ".$<a href="postconf.5.html#mydomain">mydomain</a>" to addresses that have no ".domain"
+ With locally submitted mail, append the string
+ ".$<a href="postconf.5.html#mydomain">mydomain</a>" to addresses that have no ".domain"
information.
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
sions (user+foo).
<b><a href="postconf.5.html#swap_bangpath">swap_bangpath</a> (yes)</b>
- Enable the rewriting of "site!user" into
+ Enable the rewriting of "site!user" into
"user@site".
Available in Postfix 2.2 and later:
<b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
- Don't rewrite message headers from remote clients
+ Don't rewrite message headers from remote clients
at all when this parameter is empty; otherwise, re-
- write message headers and append the specified
+ write message headers and append the specified
domain name to incomplete addresses.
<b>ROUTING CONTROLS</b>
- The following is applicable to Postfix version 2.0 and
- later. Earlier versions do not have support for: <a href="postconf.5.html#virtual_transport">vir</a>-
- <a href="postconf.5.html#virtual_transport">tual_transport</a>, <a href="postconf.5.html#relay_transport">relay_transport</a>, <a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>,
+ The following is applicable to Postfix version 2.0 and
+ later. Earlier versions do not have support for: <a href="postconf.5.html#virtual_transport">vir</a>-
+ <a href="postconf.5.html#virtual_transport">tual_transport</a>, <a href="postconf.5.html#relay_transport">relay_transport</a>, <a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>,
<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a> or <a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>.
<b><a href="postconf.5.html#local_transport">local_transport</a> (<a href="local.8.html">local</a>:$<a href="postconf.5.html#myhostname">myhostname</a>)</b>
- The default mail delivery transport and next-hop
- destination for final delivery to domains listed
- with <a href="postconf.5.html#mydestination">mydestination</a>, and for [ipaddress] destina-
- tions that match $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> or $<a href="postconf.5.html#proxy_interfaces">proxy_inter</a>-
+ The default mail delivery transport and next-hop
+ destination for final delivery to domains listed
+ with <a href="postconf.5.html#mydestination">mydestination</a>, and for [ipaddress] destina-
+ tions that match $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> or $<a href="postconf.5.html#proxy_interfaces">proxy_inter</a>-
<a href="postconf.5.html#proxy_interfaces">faces</a>.
<b><a href="postconf.5.html#virtual_transport">virtual_transport</a> (virtual)</b>
- The default mail delivery transport and next-hop
- destination for final delivery to domains listed
+ The default mail delivery transport and next-hop
+ destination for final delivery to domains listed
with $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>.
<b><a href="postconf.5.html#relay_transport">relay_transport</a> (relay)</b>
- The default mail delivery transport and next-hop
- destination for remote delivery to domains listed
+ The default mail delivery transport and next-hop
+ destination for remote delivery to domains listed
with $<a href="postconf.5.html#relay_domains">relay_domains</a>.
<b><a href="postconf.5.html#default_transport">default_transport</a> (smtp)</b>
- The default mail delivery transport and next-hop
- destination for destinations that do not match
+ The default mail delivery transport and next-hop
+ destination for destinations that do not match
$<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>, $<a href="postconf.5.html#proxy_interfaces">proxy_inter</a>-
<a href="postconf.5.html#proxy_interfaces">faces</a>, $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>, $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mail-
box_domains</a>, or $<a href="postconf.5.html#relay_domains">relay_domains</a>.
- <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' out-</b>
+ <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' out-</b>
<b>put)</b>
What Postfix features match subdomains of
"domain.tld" automatically, instead of requiring an
explicit ".domain.tld" pattern.
<b><a href="postconf.5.html#relayhost">relayhost</a> (empty)</b>
- The next-hop destination of non-local mail; over-
+ The next-hop destination of non-local mail; over-
rides non-<a href="ADDRESS_CLASS_README.html#local_domain_class">local domains</a> in recipient addresses.
<b><a href="postconf.5.html#transport_maps">transport_maps</a> (empty)</b>
Optional lookup tables with mappings from recipient
- address to (message delivery transport, next-hop
+ address to (message delivery transport, next-hop
destination).
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> (empty)</b>
- A sender-dependent override for the global <a href="postconf.5.html#relayhost">relay</a>-
+ A sender-dependent override for the global <a href="postconf.5.html#relayhost">relay</a>-
<a href="postconf.5.html#relayhost">host</a> parameter setting.
<b>ADDRESS VERIFICATION CONTROLS</b>
- Postfix version 2.1 introduces sender and recipient
- address verification. This feature is implemented by
- sending probe email messages that are not actually deliv-
- ered. By default, address verification probes use the
- same route as regular mail. To override specific aspects
- of message routing for address verification probes, spec-
+ Postfix version 2.1 introduces sender and recipient
+ address verification. This feature is implemented by
+ sending probe email messages that are not actually deliv-
+ ered. By default, address verification probes use the
+ same route as regular mail. To override specific aspects
+ of message routing for address verification probes, spec-
ify one or more of the following:
<b><a href="postconf.5.html#address_verify_local_transport">address_verify_local_transport</a> ($<a href="postconf.5.html#local_transport">local_transport</a>)</b>
address verification probes.
<b><a href="postconf.5.html#address_verify_virtual_transport">address_verify_virtual_transport</a> ($<a href="postconf.5.html#virtual_transport">virtual_transport</a>)</b>
- Overrides the <a href="postconf.5.html#virtual_transport">virtual_transport</a> parameter setting
+ Overrides the <a href="postconf.5.html#virtual_transport">virtual_transport</a> parameter setting
for address verification probes.
<b><a href="postconf.5.html#address_verify_relay_transport">address_verify_relay_transport</a> ($<a href="postconf.5.html#relay_transport">relay_transport</a>)</b>
address verification probes.
<b><a href="postconf.5.html#address_verify_default_transport">address_verify_default_transport</a> ($<a href="postconf.5.html#default_transport">default_transport</a>)</b>
- Overrides the <a href="postconf.5.html#default_transport">default_transport</a> parameter setting
+ Overrides the <a href="postconf.5.html#default_transport">default_transport</a> parameter setting
for address verification probes.
<b><a href="postconf.5.html#address_verify_relayhost">address_verify_relayhost</a> ($<a href="postconf.5.html#relayhost">relayhost</a>)</b>
- Overrides the <a href="postconf.5.html#relayhost">relayhost</a> parameter setting for
+ Overrides the <a href="postconf.5.html#relayhost">relayhost</a> parameter setting for
address verification probes.
<b><a href="postconf.5.html#address_verify_transport_maps">address_verify_transport_maps</a> ($<a href="postconf.5.html#transport_maps">transport_maps</a>)</b>
- Overrides the <a href="postconf.5.html#transport_maps">transport_maps</a> parameter setting for
+ Overrides the <a href="postconf.5.html#transport_maps">transport_maps</a> parameter setting for
address verification probes.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#address_verify_sender_dependent_relayhost_maps">address_verify_sender_dependent_relayhost_maps</a> (empty)</b>
Overrides the <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a>
- parameter setting for address verification probes.
+ parameter setting for address verification probes.
<b>MISCELLANEOUS CONTROLS</b>
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix main.cf and
+ The default location of the Postfix main.cf and
master.cf configuration files.
<b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
- How much time a Postfix daemon process may take to
- handle a request before it is terminated by a
+ How much time a Postfix daemon process may take to
+ handle a request before it is terminated by a
built-in watchdog timer.
<b><a href="postconf.5.html#empty_address_recipient">empty_address_recipient</a> (MAILER-DAEMON)</b>
- The recipient of mail addressed to the null
+ The recipient of mail addressed to the null
address.
<b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
over an internal communication channel.
<b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
- The maximum amount of time that an idle Postfix
- daemon process waits for the next service request
+ The maximum amount of time that an idle Postfix
+ daemon process waits for the next service request
before exiting.
<b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
- The maximal number of connection requests before a
+ The maximal number of connection requests before a
Postfix daemon process terminates.
<b><a href="postconf.5.html#relocated_maps">relocated_maps</a> (empty)</b>
for users or domains that no longer exist.
<b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
- The process ID of a Postfix command or daemon
+ The process ID of a Postfix command or daemon
process.
<b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
<b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
- The location of the Postfix top-level queue direc-
+ The location of the Postfix top-level queue direc-
tory.
<b><a href="postconf.5.html#show_user_unknown_table_name">show_user_unknown_table_name</a> (yes)</b>
- Display the name of the recipient table in the
+ Display the name of the recipient table in the
"User unknown" responses.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
- The mail system name that is prepended to the
- process name in syslog records, so that "smtpd"
+ The mail system name that is prepended to the
+ process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
Available in Postfix version 2.0 and later:
<b><a href="postconf.5.html#helpful_warnings">helpful_warnings</a> (yes)</b>
- Log warnings about problematic configuration set-
+ Log warnings about problematic configuration set-
tings, and provide helpful suggestions.
<b>SEE ALSO</b>
<a href="ADDRESS_VERIFICATION_README.html">ADDRESS_VERIFICATION_README</a>, Postfix address verification
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
.IP \fB-a\fR
List the available SASL server plug-in types. The SASL
plug-in type is selected with the \fBsmtpd_sasl_type\fR
-configuration parameter.
+configuration parameter by specifying one of the names
+listed below.
This feature is available with Postfix 2.3 and later.
+.RS
+.IP \fBcyrus\fR
+This server plug-in is available when Postfix is built with
+Cyrus SASL support.
+.IP \fBdovecot\fR
+This server plug-in requires the Dovecot authentication
+server.
+.RE
.IP \fB-A\fR
List the available SASL client plug-in types. The SASL
plug-in type is selected with the \fBsmtp_sasl_type\fR or
-\fBlmtp_sasl_type\fR configuration parameters.
+\fBlmtp_sasl_type\fR configuration parameters by specifying
+one of the names listed below.
This feature is available with Postfix 2.3 and later.
+.RS
+.IP \fBcyrus\fR
+This client plug-in is available when Postfix is built with
+Cyrus SASL support.
+.RE
.IP "\fB-b\fR [\fItemplate_file\fR]"
Display the message text that appears at the beginning of
delivery status notification (DSN) messages, with $\fBname\fR
The Postfix SMTP server uses this feature to reject mail from
or to addresses that end in the "@" null domain, and from addresses
that rewrite into a form that ends in the "@" null domain.
+.SH resolve_numeric_domain (default: no)
+Resolve "user@ipaddress" as "user@[ipaddress]", instead of
+rejecting the address as invalid.
+.PP
+This feature is available in Postfix 2.3 and later.
.SH rewrite_service_name (default: rewrite)
The name of the address rewriting service. This service rewrites
addresses to standard form and resolves them to a (delivery method,
Resolve an address that ends in the "@" null domain as if the
local hostname were specified, instead of rejecting the address as
invalid.
+.IP "\fBresolve_numeric_domain (no)\fR"
+Resolve "user@ipaddress" as "user@[ipaddress]", instead of
+rejecting the address as invalid.
.SH "ADDRESS REWRITING CONTROLS"
.na
.nf
s;\brelay_destination_concurrency_limit\b;<a href="postconf.5.html#relay_destination_concurrency_limit">$&</a>;g;
s;\brelay_destination_recip[-</bB>]*\n* *[<bB>]*ient_limit\b;<a href="postconf.5.html#relay_destination_recipient_limit">$&</a>;g;
s;\bresolve_null_domain\b;<a href="postconf.5.html#resolve_null_domain">$&</a>;g;
+ s;\bresolve_numeric_domain\b;<a href="postconf.5.html#resolve_numeric_domain">$&</a>;g;
s;\bsmtp_destination_concurrency_limit\b;<a href="postconf.5.html#smtp_destination_concurrency_limit">$&</a>;g;
s;\bsmtp_destination_recip[-</bB>]*\n* *[<bB>]*ient_limit\b;<a href="postconf.5.html#smtp_destination_recipient_limit">$&</a>;g;
s;\bvir[-</bB>]*\n*[ <bB>]*tual_destination_concurrency_limit\b;<a href="postconf.5.html#virtual_destination_concurrency_limit">$&</a>;g;
<li><a href="#versions">What SASL versions are supported</a>
+<li><a href="#build_dovecot">Building Postfix with Dovecot SASL
+support</a></li>
+
<li><a href="#build_sasl">Building the Cyrus SASL library</a>
<li><a href="#build_postfix">Building Postfix with Cyrus SASL
<li><a href="#server_sasl">Enabling SASL authentication in the
Postfix SMTP server</a></li>
+<li><a href="#server_dovecot">Dovecot SASL configuration for the Postfix
+SMTP server</a></li>
+
+<li><a href="#server_cyrus">Cyrus SASL configuration for the Postfix
+SMTP server</a></li>
+
<li><a href="#server_test">Testing SASL authentication in the
Postfix SMTP server</a></li>
<h2><a name="versions">What SASL versions are supported</a></h2>
-<p> This document describes Postfix with Cyrus SASL version 1 and
-Cyrus SASL version 2. Postfix version 2.3 introduces has a plug-in
-mechanism for other SASL implementations. Support for other
-implementations is currently not part of the Postfix distribution
-and will be described elsewhere. </p>
+<p> This document describes Postfix with the following SASL
+implementations: </p>
+
+<ul>
+
+<li> <p> Cyrus SASL version 1 (client and server). </p>
+
+<li> <p> Cyrus SASL version 2 (client and server). </p>
+
+<li> <p> Dovecot protocol version 1 (server only, Postfix version
+2.3 and later) </p>
+
+</ul>
+
+<p> Postfix version 2.3 introduces a plug-in mechanism that provides
+support for multiple SASL implementations. To find out what
+implementations are built into Postfix, use the following commands:
+</p>
+
+<blockquote>
+<pre>
+% postconf -a (SASL support in the SMTP server)
+% postconf -A (SASL support in the SMTP+LMTP client)
+</pre>
+</blockquote>
+
+<p> Needless to say, these commands are not available in Postfix
+versions before 2.3. </p>
+
+<h2><a name="build_dovecot">Building Postfix with Dovecot SASL
+support</a></h2>
+
+<p> Dovecot is available via http://www.dovecot.org/. It uses its
+own daemon process for authentication. Building Postfix with Dovecot
+SASL support is relatively easy, because there is no need to link
+extra libraries into Postfix. </p>
+
+<p> To generate the necessary Makefiles, execute the following
+in the Postfix top-level directory: </p>
+
+<pre>
+% make makefiles CCARGS='-DUSE_SASL_AUTH -DDEF_SASL_SERVER=\"dovecot\"'
+</pre>
+
+<p> Notes: </p>
+
+<ul>
+
+<li> <p> The "-DDEF_SASL_SERVER" stuff is not necessary; it just
+makes Postfix configuration a little more convenient because you
+don't have to specify the SASL plug-in type in the Postfix main.cf
+file. </p>
+
+<li> <p> If you also want support for LDAP or TLS, you will have to merge
+their CCARGS and AUXLIBS into the above command line. </p>
+
+<li> <p> After this, proceed with "<tt>make</tt>" as described in the
+INSTALL document. </p>
+
+</ul>
<h2><a name="build_sasl">Building the Cyrus SASL library</a></h2>
<p> Note: the SASL login names will be shared with the entire world.
</p>
+<h2><a name="server_dovecot">Dovecot SASL configuration for the
+Postfix SMTP server</a></h2>
+
+<p> On the Postfix side you need to specify the location of the
+Dovecot authentication daemon socket. We use a pathname relative
+to the Postfix queue directory, so that it will work whether or not
+Postfix runs chrooted: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+ smtpd_sasl_type = dovecot
+ smtpd_sasl_path = private/auth
+</pre>
+</blockquote>
+
+<p> On the Dovecot side you also need to specify the Dovecot
+authentication daemon socket. In this case we specify an
+absolute pathname. In the example we assume that the
+Postfix queue is under /var/spool/postfix/. </p>
+
+<blockquote>
+<pre>
+/some/where/dovecot.conf:
+ auth default {
+ ..
+ socket listen {
+ client {
+ path = /var/spool/postfix/private/auth
+ mode = 0666
+ }
+ }
+ }
+</pre>
+</blockquote>
+
+<p> See the Dovecot documentation for how to configure the Dovecot
+authentication server. </p>
+
+<h2><a name="server_cyrus">Cyrus SASL configuration for the Postfix
+SMTP server</a></h2>
+
<p> In /usr/local/lib/sasl/smtpd.conf (Cyrus SASL version 1.5.5) or
/usr/local/lib/sasl2/smtpd.conf (Cyrus SASL version 2.1.1) you need to
specify how the server should validate client passwords. </p>
<li> Wietse made another iteration through the code to add
plug-in support for multiple implementations.
+<li> The Dovecot plug-in was originally implemented by Timo Sirainen
+of Procontrol, Finland.
+
</ul>
</body>
</p>
<p> This feature is available in Postfix 2.3 and later. </p>
+
+%PARAM resolve_numeric_domain no
+
+<p> Resolve "user@ipaddress" as "user@[ipaddress]", instead of
+rejecting the address as invalid. </p>
+
+<p> This feature is available in Postfix 2.3 and later.
*/
typedef struct DNS_RR {
char *name; /* name, mystrdup()ed */
+ char *rname; /* reply name, mystrdup()ed */
unsigned short type; /* T_A, T_CNAME, etc. */
unsigned short class; /* C_IN, etc. */
unsigned int ttl; /* always */
/*
* dns_rr.c
*/
-extern DNS_RR *dns_rr_create(const char *, ushort, ushort,
+extern DNS_RR *dns_rr_create(const char *, const char *,
+ ushort, ushort,
unsigned, unsigned,
const char *, size_t);
extern void dns_rr_free(DNS_RR *);
/* dns_get_rr - extract resource record from name server reply */
-static int dns_get_rr(DNS_RR **list, DNS_REPLY *reply, unsigned char *pos,
- char *rr_name, DNS_FIXED *fixed)
+static int dns_get_rr(DNS_RR **list, const char *orig_name, DNS_REPLY *reply,
+ unsigned char *pos, char *rr_name,
+ DNS_FIXED *fixed)
{
char temp[DNS_NAME_LEN];
ssize_t data_len;
*dst = 0;
break;
}
- *list = dns_rr_create(rr_name, fixed->type, fixed->class, fixed->ttl,
- pref, temp, data_len);
+ *list = dns_rr_create(orig_name, rr_name, fixed->type, fixed->class,
+ fixed->ttl, pref, temp, data_len);
return (DNS_OK);
}
/* dns_get_answer - extract answers from name server reply */
-static int dns_get_answer(DNS_REPLY *reply, int type,
+static int dns_get_answer(const char *orig_name, DNS_REPLY *reply, int type,
DNS_RR **rrlist, VSTRING *fqdn, char *cname, int c_len)
{
char rr_name[DNS_NAME_LEN];
CORRUPT(DNS_RETRY);
if (type == fixed.type || type == T_ANY) { /* requested type */
if (rrlist) {
- if ((status = dns_get_rr(&rr, reply, pos, rr_name, &fixed)) == DNS_OK) {
+ if ((status = dns_get_rr(&rr, orig_name, reply, pos, rr_name,
+ &fixed)) == DNS_OK) {
resource_found++;
*rrlist = dns_rr_append(*rrlist, rr);
} else if (not_found_status != DNS_RETRY)
static DNS_REPLY reply;
int count;
int status;
+ const char *orig_name = name;
/*
* DJBDNS produces a bogus A record when given a numerical hostname.
* Extract resource records of the requested type. Pick up CNAME
* information just in case the requested data is not found.
*/
- status = dns_get_answer(&reply, type, rrlist, fqdn, cname, c_len);
+ status = dns_get_answer(orig_name, &reply, type, rrlist, fqdn,
+ cname, c_len);
switch (status) {
default:
if (why)
/* SYNOPSIS
/* #include <dns.h>
/*
-/* DNS_RR *dns_rr_create(name, type, class, ttl, preference,
+/* DNS_RR *dns_rr_create(name, rname, type, class, ttl, preference,
/* data, data_len)
/* const char *name;
+/* const char *rname;
/* unsigned short type;
/* unsigned short class;
/* unsigned int ttl;
/* information, and maintain lists of DNS resource records.
/*
/* dns_rr_create() creates and initializes one resource record.
-/* The \fIname\fR record specifies the record name.
+/* The \fIname\fR field specifies the query name.
+/* The \fIrname\fR field specifies the reply name.
/* \fIpreference\fR is used for MX records; \fIdata\fR is a null
/* pointer or specifies optional resource-specific data;
/* \fIdata_len\fR is the amount of resource-specific data.
/* dns_rr_create - fill in resource record structure */
-DNS_RR *dns_rr_create(const char *name, ushort type, ushort class,
+DNS_RR *dns_rr_create(const char *name, const char *rname,
+ ushort type, ushort class,
unsigned int ttl, unsigned pref,
const char *data, size_t data_len)
{
rr = (DNS_RR *) mymalloc(sizeof(*rr) + data_len - 1);
rr->name = mystrdup(name);
+ rr->rname = mystrdup(rname);
rr->type = type;
rr->class = class;
rr->ttl = ttl;
if (rr->next)
dns_rr_free(rr->next);
myfree(rr->name);
+ myfree(rr->rname);
myfree((char *) rr);
}
}
dst = (DNS_RR *) mymalloc(len);
memcpy((char *) dst, (char *) src, len);
dst->name = mystrdup(src->name);
+ dst->rname = mystrdup(src->rname);
dst->next = 0;
return (dst);
}
#define DUMMY_TTL 0
if (sa->sa_family == AF_INET) {
- return (dns_rr_create(hostname, T_A, C_IN, DUMMY_TTL, pref,
+ return (dns_rr_create(hostname, hostname, T_A, C_IN, DUMMY_TTL, pref,
(char *) &SOCK_ADDR_IN_ADDR(sa),
sizeof(SOCK_ADDR_IN_ADDR(sa))));
#ifdef HAS_IPV6
} else if (sa->sa_family == AF_INET6) {
- return (dns_rr_create(hostname, T_AAAA, C_IN, DUMMY_TTL, pref,
+ return (dns_rr_create(hostname, hostname, T_AAAA, C_IN, DUMMY_TTL, pref,
(char *) &SOCK_ADDR_IN6_ADDR(sa),
sizeof(SOCK_ADDR_IN6_ADDR(sa))));
#endif
MAI_HOSTADDR_STR host;
while (rr) {
- printf("%s: ttl: %9d ", rr->name, rr->ttl);
+ printf("%s: ttl: %9d ", rr->rname, rr->ttl);
switch (rr->type) {
case T_A:
#ifdef T_AAAA
* and what Postfix exports to the external world.
*/
#define VAR_IMPORT_ENVIRON "import_environment"
-#define DEF_IMPORT_ENVIRON "MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG TZ XAUTHORITY DISPLAY"
+#define DEF_IMPORT_ENVIRON "MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG TZ XAUTHORITY DISPLAY LANG=C"
extern char *var_import_environ;
#define VAR_EXPORT_ENVIRON "export_environment"
-#define DEF_EXPORT_ENVIRON "TZ MAIL_CONFIG"
+#define DEF_EXPORT_ENVIRON "TZ MAIL_CONFIG LANG"
extern char *var_export_environ;
/*
#define DEF_RESOLVE_NULLDOM 0
extern bool var_resolve_nulldom;
+#define VAR_RESOLVE_NUM_DOM "resolve_numeric_domain"
+#define DEF_RESOLVE_NUM_DOM 0
+extern bool var_resolve_num_dom;
+
/*
* Service names. The transport (TCP, FIFO or UNIX-domain) type is frozen
* because you cannot simply mix them, and accessibility (private/public) is
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20051221"
+#define MAIL_RELEASE_DATE "20051222"
#define MAIL_VERSION_NUMBER "2.3"
#ifdef SNAPSHOT
/* .IP \fB-a\fR
/* List the available SASL server plug-in types. The SASL
/* plug-in type is selected with the \fBsmtpd_sasl_type\fR
-/* configuration parameter.
+/* configuration parameter by specifying one of the names
+/* listed below.
/*
/* This feature is available with Postfix 2.3 and later.
+/* .RS
+/* .IP \fBcyrus\fR
+/* This server plug-in is available when Postfix is built with
+/* Cyrus SASL support.
+/* .IP \fBdovecot\fR
+/* This server plug-in requires the Dovecot authentication
+/* server.
+/* .RE
/* .IP \fB-A\fR
/* List the available SASL client plug-in types. The SASL
/* plug-in type is selected with the \fBsmtp_sasl_type\fR or
-/* \fBlmtp_sasl_type\fR configuration parameters.
+/* \fBlmtp_sasl_type\fR configuration parameters by specifying
+/* one of the names listed below.
/*
/* This feature is available with Postfix 2.3 and later.
+/* .RS
+/* .IP \fBcyrus\fR
+/* This client plug-in is available when Postfix is built with
+/* Cyrus SASL support.
+/* .RE
/* .IP "\fB-b\fR [\fItemplate_file\fR]"
/* Display the message text that appears at the beginning of
/* delivery status notification (DSN) messages, with $\fBname\fR
(VSTRING *) 0, (VSTRING *) 0);
if (dns_status == DNS_NOTFOUND && h_errno == NO_DATA) {
if (type == T_MX) {
- server_list = dns_rr_create(domain, type, C_IN, 0, 0,
+ server_list = dns_rr_create(domain, domain, type, C_IN, 0, 0,
domain, strlen(domain) + 1);
dns_status = DNS_OK;
} else if (type == T_NS) {
IF_VERIFIED(state->tls_context->issuer_CN),
ATTR_TYPE_STR, MAIL_ATTR_CCERT_FINGERPRINT,
IF_VERIFIED(state->tls_context->peer_fingerprint),
-#define IF_ENCRYPTED(x) ((state->tls_context && ((x) != 0)) ? (x) : "")
+#define IF_ENCRYPTED(x, y) ((state->tls_context && ((x) != 0)) ? (x) : (y))
ATTR_TYPE_STR, MAIL_ATTR_CRYPTO_PROTOCOL,
- IF_ENCRYPTED(state->tls_context->protocol),
+ IF_ENCRYPTED(state->tls_context->protocol, ""),
ATTR_TYPE_STR, MAIL_ATTR_CRYPTO_CIPHER,
- IF_ENCRYPTED(state->tls_context->cipher_name),
+ IF_ENCRYPTED(state->tls_context->cipher_name, ""),
ATTR_TYPE_NUM, MAIL_ATTR_CRYPTO_KEYSIZE,
- state->tls_context->cipher_usebits,
+ IF_ENCRYPTED(state->tls_context->cipher_usebits, 0),
#endif
ATTR_TYPE_END,
ATTR_FLAG_MISSING, /* Reply attributes. */
*/
tok822_internalize(nextrcpt, tree, TOK822_STR_DEFL);
rcpt_domain = strrchr(STR(nextrcpt), '@') + 1;
- if (*rcpt_domain == '[' ? !valid_mailhost_literal(rcpt_domain, DONT_GRIPE) :
- !valid_hostname(rcpt_domain, DONT_GRIPE))
- *flags |= RESOLVE_FLAG_ERROR;
+ if (*rcpt_domain == '[') {
+ if (!valid_mailhost_literal(rcpt_domain, DONT_GRIPE))
+ *flags |= RESOLVE_FLAG_ERROR;
+ } else if (!valid_hostname(rcpt_domain, DONT_GRIPE)) {
+ if (var_resolve_num_dom && valid_hostaddr(rcpt_domain, DONT_GRIPE)) {
+ vstring_insert(nextrcpt, rcpt_domain - STR(nextrcpt), "[", 1);
+ vstring_strcat(nextrcpt, "]");
+ rcpt_domain = strrchr(STR(nextrcpt), '@') + 1;
+ if (resolve_local(rcpt_domain)) /* XXX */
+ domain = 0;
+ } else {
+ *flags |= RESOLVE_FLAG_ERROR;
+ }
+ }
tok822_free_tree(tree);
tree = 0;
/* Resolve an address that ends in the "@" null domain as if the
/* local hostname were specified, instead of rejecting the address as
/* invalid.
+/* .IP "\fBresolve_numeric_domain (no)\fR"
+/* Resolve "user@ipaddress" as "user@[ipaddress]", instead of
+/* rejecting the address as invalid.
/* ADDRESS REWRITING CONTROLS
/* .ad
/* .fi
int var_resolve_nulldom;
char *var_remote_rwr_domain;
char *var_snd_relay_maps;
+int var_resolve_num_dom;
/*
* Shadow personality for address verification.
VAR_RESOLVE_DEQUOTED, DEF_RESOLVE_DEQUOTED, &var_resolve_dequoted,
VAR_SHOW_UNK_RCPT_TABLE, DEF_SHOW_UNK_RCPT_TABLE, &var_show_unk_rcpt_table,
VAR_RESOLVE_NULLDOM, DEF_RESOLVE_NULLDOM, &var_resolve_nulldom,
+ VAR_RESOLVE_NUM_DOM, DEF_RESOLVE_NUM_DOM, &var_resolve_num_dom,
0,
};
#endif
/*
- * Making the ctype.h macros not more expensive than necessary. On some
- * systems, ctype.h misbehaves with non-ASCII and/or negative characters.
+ * Safety. On some systems, ctype.h misbehaves with non-ASCII or negative
+ * characters. More importantly, Postfix uses the ISXXX() macros to ensure
+ * protocol compliance, so we have to rule out non-ASCII characters.
*/
-#define _UCHAR_(c) ((unsigned char)(c))
-#ifdef UNSAFE_CTYPE
#define ISASCII(c) isascii(_UCHAR_(c))
+#define _UCHAR_(c) ((unsigned char)(c))
#define ISALNUM(c) (ISASCII(c) && isalnum(c))
#define ISALPHA(c) (ISASCII(c) && isalpha(c))
#define ISCNTRL(c) (ISASCII(c) && iscntrl(c))
#define ISUPPER(c) (ISASCII(c) && isupper(c))
#define TOLOWER(c) (ISUPPER(c) ? tolower(c) : (c))
#define TOUPPER(c) (ISLOWER(c) ? toupper(c) : (c))
-#else
-#define ISASCII(c) isascii(_UCHAR_(c))
-#define ISALNUM(c) isalnum(_UCHAR_(c))
-#define ISALPHA(c) isalpha(_UCHAR_(c))
-#define ISCNTRL(c) iscntrl(_UCHAR_(c))
-#define ISDIGIT(c) isdigit(_UCHAR_(c))
-#define ISGRAPH(c) isgraph(_UCHAR_(c))
-#define ISLOWER(c) islower(_UCHAR_(c))
-#define ISPRINT(c) isprint(_UCHAR_(c))
-#define ISPUNCT(c) ispunct(_UCHAR_(c))
-#define ISSPACE(c) isspace(_UCHAR_(c))
-#define ISUPPER(c) isupper(_UCHAR_(c))
-#define TOLOWER(c) tolower(_UCHAR_(c))
-#define TOUPPER(c) toupper(_UCHAR_(c))
-#endif
/*
* Scaffolding. I don't want to lose messages while the program is under
VSTRING_ADDCH(result, ch);
continue;
} else if (ch == '\a') { /* \a -> audible bell */
- vstring_strcat(result, "\a");
+ vstring_strcat(result, "\\a");
continue;
} else if (ch == '\b') { /* \b -> backspace */
- vstring_strcat(result, "\b");
+ vstring_strcat(result, "\\b");
continue;
} else if (ch == '\f') { /* \f -> formfeed */
- vstring_strcat(result, "\f");
+ vstring_strcat(result, "\\f");
continue;
} else if (ch == '\n') { /* \n -> newline */
- vstring_strcat(result, "\n");
+ vstring_strcat(result, "\\n");
continue;
} else if (ch == '\r') { /* \r -> carriagereturn */
- vstring_strcat(result, "\r");
+ vstring_strcat(result, "\\r");
continue;
} else if (ch == '\t') { /* \t -> horizontal tab */
- vstring_strcat(result, "\t");
+ vstring_strcat(result, "\\t");
continue;
} else if (ch == '\v') { /* \v -> vertical tab */
- vstring_strcat(result, "\v");
+ vstring_strcat(result, "\\v");
continue;
}
}
- vstring_sprintf_append(result, "\\%03d", ch);
+ if (ISDIGIT(*UCHAR(data)))
+ vstring_sprintf_append(result, "\\%03d", ch);
+ else
+ vstring_sprintf_append(result, "\\%d", ch);
}
VSTRING_TERMINATE(result);
return (result);
#ifdef TEST
#include <stdlib.h>
+#include <string.h>
+#include <msg.h>
#include <vstring_vstream.h>
-int main(int unused_argc, char **unused_argv)
+int main(int argc, char **argv)
{
VSTRING *in = vstring_alloc(10);
VSTRING *out = vstring_alloc(10);
+ int un_escape = 1;
- while (vstring_fgets_nonl(in, VSTREAM_IN)) {
- unescape(out, vstring_str(in));
- vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out));
+ if (argc > 2 || (un_escape = strcmp(argv[1], "-e")) != 0)
+ msg_fatal("usage: %s [-e (escape)]", argv[0]);
+
+ if (un_escape) {
+ while (vstring_fgets_nonl(in, VSTREAM_IN)) {
+ unescape(out, vstring_str(in));
+ vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out));
+ }
+ } else {
+ while (vstring_fgets(in, VSTREAM_IN)) {
+ escape(out, vstring_str(in), VSTRING_LEN(in));
+ vstream_fwrite(VSTREAM_OUT, vstring_str(out), VSTRING_LEN(out));
+ }
}
vstream_fflush(VSTREAM_OUT);
exit(0);
/* VSTRING *vp;
/* int ch;
/*
+/* VSTRING *vstring_insert(vp, start, src, len)
+/* VSTRING *vp;
+/* ssize_t start;
+/* const char *src;
+/* ssize_t len;
+/*
/* VSTRING *vstring_prepend(vp, src, len)
/* VSTRING *vp;
/* const char *src;
/*
/* vstring_memchr() locates a byte in a variable-length string.
/*
+/* vstring_insert() inserts a buffer content into a variable-length
+/* string at the specified start position. The result is
+/* null-terminated.
+/*
/* vstring_prepend() prepends a buffer content to a variable-length
/* string. The result is null-terminated.
/*
return (0);
}
+/* vstring_insert - insert text into string */
+
+VSTRING *vstring_insert(VSTRING *vp, ssize_t start, const char *buf, ssize_t len)
+{
+ const char *myname = "vstring_insert";
+ ssize_t new_len;
+
+ /*
+ * Sanity check.
+ */
+ if (start < 0 || start >= VSTRING_LEN(vp))
+ msg_panic("vstring_insert: bad start %ld", (long) start);
+ if (len < 0)
+ msg_panic("vstring_insert: bad length %ld", (long) len);
+
+ /*
+ * Move the existing content and copy the new content.
+ */
+ new_len = VSTRING_LEN(vp) + len;
+ VSTRING_SPACE(vp, len);
+ memmove(vstring_str(vp) + start + len, vstring_str(vp) + start,
+ VSTRING_LEN(vp) - start);
+ memcpy(vstring_str(vp) + start, buf, len);
+ VSTRING_AT_OFFSET(vp, new_len);
+ VSTRING_TERMINATE(vp);
+ return (vp);
+}
+
/* vstring_prepend - prepend text to string */
VSTRING *vstring_prepend(VSTRING *vp, const char *buf, ssize_t len)
extern VSTRING *vstring_memcpy(VSTRING *, const char *, ssize_t);
extern VSTRING *vstring_memcat(VSTRING *, const char *, ssize_t);
extern char *vstring_memchr(VSTRING *, int);
+extern VSTRING *vstring_insert(VSTRING *, ssize_t, const char *, ssize_t);
extern VSTRING *vstring_prepend(VSTRING *, const char *, ssize_t);
extern VSTRING *PRINTFLIKE(2, 3) vstring_sprintf(VSTRING *, const char *,...);
extern VSTRING *PRINTFLIKE(2, 3) vstring_sprintf_append(VSTRING *, const char *,...);
SHELL = /bin/sh
SRCS = xsasl_server.c xsasl_cyrus_server.c xsasl_cyrus_log.c \
- xsasl_cyrus_security.c xsasl_client.c xsasl_cyrus_client.c
+ xsasl_cyrus_security.c xsasl_client.c xsasl_cyrus_client.c \
+ xsasl_dovecot_server.c
OBJS = xsasl_server.o xsasl_cyrus_server.o xsasl_cyrus_log.o \
- xsasl_cyrus_security.o xsasl_client.o xsasl_cyrus_client.o
+ xsasl_cyrus_security.o xsasl_client.o xsasl_cyrus_client.o \
+ xsasl_dovecot_server.o
HDRS = xsasl.h
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
xsasl_cyrus_server.o: xsasl_cyrus.h
xsasl_cyrus_server.o: xsasl_cyrus_common.h
xsasl_cyrus_server.o: xsasl_cyrus_server.c
+xsasl_dovecot_server.o: ../../include/argv.h
+xsasl_dovecot_server.o: ../../include/connect.h
+xsasl_dovecot_server.o: ../../include/iostuff.h
+xsasl_dovecot_server.o: ../../include/mail_params.h
+xsasl_dovecot_server.o: ../../include/msg.h
+xsasl_dovecot_server.o: ../../include/mymalloc.h
+xsasl_dovecot_server.o: ../../include/split_at.h
+xsasl_dovecot_server.o: ../../include/stringops.h
+xsasl_dovecot_server.o: ../../include/sys_defs.h
+xsasl_dovecot_server.o: ../../include/vbuf.h
+xsasl_dovecot_server.o: ../../include/vstream.h
+xsasl_dovecot_server.o: ../../include/vstring.h
+xsasl_dovecot_server.o: ../../include/vstring_vstream.h
+xsasl_dovecot_server.o: xsasl.h
+xsasl_dovecot_server.o: xsasl_dovecot.h
+xsasl_dovecot_server.o: xsasl_dovecot_server.c
xsasl_server.o: ../../include/argv.h
xsasl_server.o: ../../include/msg.h
xsasl_server.o: ../../include/mymalloc.h
xsasl_server.o: ../../include/vstring.h
xsasl_server.o: xsasl.h
xsasl_server.o: xsasl_cyrus.h
+xsasl_server.o: xsasl_dovecot.h
xsasl_server.o: xsasl_server.c
--- /dev/null
+#ifndef _XSASL_DOVECOT_H_INCLUDED_
+#define _XSASL_DOVECOT_H_INCLUDED_
+
+/*++
+/* NAME
+/* xsasl_dovecot 3h
+/* SUMMARY
+/* Dovecot SASL plug-in
+/* SYNOPSIS
+/* #include <xsasl_dovecot.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * XSASL library.
+ */
+#include <xsasl.h>
+
+#if defined(USE_SASL_AUTH)
+
+ /*
+ * SASL protocol interface
+ */
+#define XSASL_TYPE_DOVECOT "dovecot"
+
+extern XSASL_SERVER_IMPL *xsasl_dovecot_server_init(const char *, const char *);
+
+#endif
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* xsasl_dovecot_server 3
+/* SUMMARY
+/* Dovecot SASL server-side plug-in
+/* SYNOPSIS
+/* XSASL_SERVER_IMPL *xsasl_dovecot_server_init(server_type, appl_name)
+/* const char *server_type;
+/* const char *appl_name;
+/* DESCRIPTION
+/* This module implements the Dovecot SASL server-side authentication
+/* plug-in.
+/*
+/* DIAGNOSTICS
+/* Fatal: out of memory.
+/*
+/* Panic: interface violation.
+/*
+/* Other: the routines log a warning and return an error result
+/* as specified in xsasl_server(3).
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Initial implementation by:
+/* Timo Sirainen
+/* Procontrol
+/* Finland
+/*
+/* Adopted by:
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <connect.h>
+#include <split_at.h>
+#include <stringops.h>
+#include <vstream.h>
+#include <vstring_vstream.h>
+
+/* Global library. */
+
+#include <mail_params.h>
+
+/* Application-specific. */
+
+#include <xsasl.h>
+#include <xsasl_dovecot.h>
+
+#ifdef USE_SASL_AUTH
+
+/* Major version changes are not backwards compatible,
+ minor version numbers can be ignored. */
+#define AUTH_PROTOCOL_MAJOR_VERSION 1
+#define AUTH_PROTOCOL_MINOR_VERSION 0
+
+ /*
+ * Class variables.
+ */
+typedef struct {
+ XSASL_SERVER_IMPL xsasl;
+ VSTREAM *sasl_stream;
+ char *socket_path;
+ char *mechanism_list; /* applicable mechanisms */
+ unsigned int request_id_counter;
+} XSASL_DOVECOT_SERVER_IMPL;
+
+ /*
+ * The XSASL_DOVECOT_SERVER object is derived from the generic XSASL_SERVER
+ * object.
+ */
+typedef struct {
+ XSASL_SERVER xsasl; /* generic members, must be first */
+ XSASL_DOVECOT_SERVER_IMPL *impl;
+ unsigned int last_request_id;
+ char *service;
+ char *username; /* authenticated user */
+ VSTRING *sasl_line;
+} XSASL_DOVECOT_SERVER;
+
+ /*
+ * Forward declarations.
+ */
+static void xsasl_dovecot_server_done(XSASL_SERVER_IMPL *);
+static XSASL_SERVER *xsasl_dovecot_server_create(XSASL_SERVER_IMPL *,
+ VSTREAM *,
+ const char *,
+ const char *,
+ const char *);
+static void xsasl_dovecot_server_free(XSASL_SERVER *);
+static int xsasl_dovecot_server_first(XSASL_SERVER *, const char *,
+ const char *, VSTRING *);
+static int xsasl_dovecot_server_next(XSASL_SERVER *, const char *, VSTRING *);
+static const char *xsasl_dovecot_server_get_mechanism_list(XSASL_SERVER *);
+static const char *xsasl_dovecot_server_get_username(XSASL_SERVER *);
+
+static int xsasl_dovecot_server_connect(XSASL_DOVECOT_SERVER_IMPL *xp)
+{
+ const char *myname = "xsasl_dovecot_server_connect";
+ VSTRING *line_str, *mechanisms_str;
+ VSTREAM *sasl_stream;
+ char *line, *cmd, *mech_name;
+ unsigned int major_version, minor_version;
+ int fd, success;
+
+ if (msg_verbose)
+ msg_info("%s: Connecting", myname);
+
+ if ((fd = unix_connect(xp->socket_path, BLOCKING, 0)) < 0) {
+ msg_warn("SASL: Connect to %s failed: %m", xp->socket_path);
+ return (-1);
+ }
+ sasl_stream = vstream_fdopen(fd, O_RDWR);
+ vstream_control(sasl_stream, VSTREAM_CTL_PATH,
+ xp->socket_path, VSTREAM_CTL_END);
+
+ vstream_fprintf(sasl_stream,
+ "VERSION\t%u\t%u\n"
+ "CPID\t%u\n",
+ AUTH_PROTOCOL_MAJOR_VERSION,
+ AUTH_PROTOCOL_MINOR_VERSION,
+ (unsigned int) getpid());
+ if (vstream_fflush(sasl_stream) == VSTREAM_EOF) {
+ msg_warn("SASL: Couldn't send handshake: %m");
+ return (-1);
+ }
+ success = 0;
+ line_str = vstring_alloc(256);
+ mechanisms_str = vstring_alloc(128);
+ while (vstring_get_nonl(line_str, sasl_stream) != VSTREAM_EOF) {
+ line = vstring_str(line_str);
+
+ if (msg_verbose)
+ msg_info("%s: auth reply: %s", myname, line);
+
+ cmd = line;
+ line = split_at(line, '\t');
+
+ if (strcmp(cmd, "VERSION") == 0) {
+ if (sscanf(line, "%u\t%u", &major_version, &minor_version) != 2) {
+ msg_warn("SASL: Protocol version error");
+ break;
+ }
+ if (major_version != AUTH_PROTOCOL_MAJOR_VERSION) {
+ /* Major version is different from ours. */
+ msg_warn("SASL: Protocol version mismatch (%d vs. %d)",
+ major_version, AUTH_PROTOCOL_MAJOR_VERSION);
+ break;
+ }
+ } else if (strcmp(cmd, "MECH") == 0 && line != NULL) {
+ mech_name = line;
+ line = split_at(line, '\t');
+
+ if (VSTRING_LEN(mechanisms_str) > 0)
+ VSTRING_ADDCH(mechanisms_str, ' ');
+ vstring_strcat(mechanisms_str, mech_name);
+ } else if (strcmp(cmd, "DONE") == 0) {
+ /* Handshake finished. */
+ success = 1;
+ break;
+ } else {
+ /* ignore any unknown commands */
+ }
+ }
+ vstring_free(line_str);
+
+ if (!success) {
+ /* handshake failed */
+ vstring_free(mechanisms_str);
+ (void) vstream_fclose(sasl_stream);
+ return (-1);
+ }
+ xp->sasl_stream = sasl_stream;
+ xp->mechanism_list =
+ translit(vstring_export(mechanisms_str), "\t", " ");
+ if (msg_verbose)
+ msg_info("%s: Mechanisms: %s", myname, xp->mechanism_list);
+ return (0);
+}
+
+static void xsasl_dovecot_server_disconnect(XSASL_DOVECOT_SERVER_IMPL *xp)
+{
+ if (xp->sasl_stream) {
+ (void) vstream_fclose(xp->sasl_stream);
+ xp->sasl_stream = 0;
+ }
+ if (xp->mechanism_list) {
+ myfree(xp->mechanism_list);
+ xp->mechanism_list = 0;
+ }
+}
+
+/* xsasl_dovecot_server_init - create implementation handle */
+
+XSASL_SERVER_IMPL *xsasl_dovecot_server_init(const char *unused_server_type,
+ const char *path_info)
+{
+ XSASL_DOVECOT_SERVER_IMPL *xp;
+
+ xp = (XSASL_DOVECOT_SERVER_IMPL *) mymalloc(sizeof(*xp));
+ xp->xsasl.create = xsasl_dovecot_server_create;
+ xp->xsasl.done = xsasl_dovecot_server_done;
+ xp->socket_path = mystrdup(path_info);
+ xp->sasl_stream = 0;
+ xp->mechanism_list = 0;
+ xp->request_id_counter = 0;
+ return (&xp->xsasl);
+}
+
+/* xsasl_dovecot_server_done - dispose of implementation */
+
+static void xsasl_dovecot_server_done(XSASL_SERVER_IMPL *impl)
+{
+ XSASL_DOVECOT_SERVER_IMPL *xp = (XSASL_DOVECOT_SERVER_IMPL *) impl;
+
+ xsasl_dovecot_server_disconnect(xp);
+ myfree(xp->socket_path);
+ myfree((char *) impl);
+}
+
+/* xsasl_dovecot_server_create - create server instance */
+
+static XSASL_SERVER *xsasl_dovecot_server_create(XSASL_SERVER_IMPL *impl,
+ VSTREAM *unused_stream,
+ const char *service,
+ const char *realm,
+ const char *unused_sec_props)
+{
+ const char *myname = "xsasl_dovecot_server_create";
+ XSASL_DOVECOT_SERVER *server;
+
+ if (msg_verbose)
+ msg_info("%s: SASL service=%s, realm=%s",
+ myname, service, realm ? realm : "(null)");
+
+ /*
+ * Extend the XSASL_SERVER_IMPL object with our own data. We use
+ * long-lived conversion buffers rather than local variables to avoid
+ * memory leaks in case of read/write timeout or I/O error.
+ */
+ server = (XSASL_DOVECOT_SERVER *) mymalloc(sizeof(*server));
+ server->xsasl.free = xsasl_dovecot_server_free;
+ server->xsasl.first = xsasl_dovecot_server_first;
+ server->xsasl.next = xsasl_dovecot_server_next;
+ server->xsasl.get_mechanism_list = xsasl_dovecot_server_get_mechanism_list;
+ server->xsasl.get_username = xsasl_dovecot_server_get_username;
+ server->impl = (XSASL_DOVECOT_SERVER_IMPL *) impl;
+ server->sasl_line = vstring_alloc(256);
+ server->username = 0;
+ server->service = mystrdup(service);
+ server->last_request_id = 0;
+
+ return (&server->xsasl);
+}
+
+/* xsasl_dovecot_server_get_mechanism_list - get available mechanisms */
+
+static const char *xsasl_dovecot_server_get_mechanism_list(XSASL_SERVER *xp)
+{
+ XSASL_DOVECOT_SERVER *server = (XSASL_DOVECOT_SERVER *) xp;
+
+ if (!server->impl->sasl_stream) {
+ if (xsasl_dovecot_server_connect(server->impl) < 0)
+ return (0);
+ }
+ return (server->impl->mechanism_list);
+}
+
+/* xsasl_dovecot_server_free - destroy server instance */
+
+static void xsasl_dovecot_server_free(XSASL_SERVER *xp)
+{
+ XSASL_DOVECOT_SERVER *server = (XSASL_DOVECOT_SERVER *) xp;
+
+ vstring_free(server->sasl_line);
+ if (server->username)
+ myfree(server->username);
+ myfree(server->service);
+ myfree((char *) server);
+}
+
+/* xsasl_dovecot_server_auth_response - encode server first/next response */
+
+static int xsasl_dovecot_parse_reply(XSASL_DOVECOT_SERVER *server, char **line)
+{
+ char *id;
+
+ if (*line == NULL) {
+ msg_warn("SASL: Protocol error");
+ return -1;
+ }
+ id = *line;
+ *line = split_at(*line, '\t');
+
+ if (strtoul(id, NULL, 0) != server->last_request_id) {
+ /* reply to another request, shouldn't really happen.. */
+ return -1;
+ }
+ return 0;
+}
+
+static void xsasl_dovecot_parse_reply_args(XSASL_DOVECOT_SERVER *server,
+ char *line, VSTRING *reply,
+ int success)
+{
+ char *next;
+
+ if (server->username) {
+ myfree(server->username);
+ server->username = 0;
+ }
+
+ /*
+ * Note: TAB is part of the Dovecot protocol and must not appear in
+ * legitimate Dovecot usernames, otherwise the protocol would break.
+ */
+ for (; line != NULL; line = next) {
+ next = split_at(line, '\t');
+ if (strncmp(line, "user=", 5) == 0) {
+ server->username = mystrdup(line + 5);
+ printable(server->username, '?');
+ } else if (strncmp(line, "reason=", 7) == 0) {
+ if (!success) {
+ printable(line + 7, '?');
+ vstring_strcpy(reply, line + 7);
+ }
+ }
+ }
+}
+
+/* xsasl_dovecot_handle_reply - receive and process auth reply */
+
+static int xsasl_dovecot_handle_reply(XSASL_DOVECOT_SERVER *server,
+ VSTRING *reply)
+{
+ char *myname = "xsasl_dovecot_handle_reply";
+ char *line, *cmd;
+
+ while (vstring_get_nonl(server->sasl_line,
+ server->impl->sasl_stream) != VSTREAM_EOF) {
+ line = vstring_str(server->sasl_line);
+
+ if (msg_verbose)
+ msg_info("%s: auth reply: %s", myname, line);
+
+ cmd = line;
+ line = split_at(line, '\t');
+
+ if (strcmp(cmd, "OK") == 0) {
+ if (xsasl_dovecot_parse_reply(server, &line) == 0) {
+ /* authentication successful */
+ xsasl_dovecot_parse_reply_args(server, line, reply, 1);
+ return XSASL_AUTH_DONE;
+ }
+ } else if (strcmp(cmd, "CONT") == 0) {
+ if (xsasl_dovecot_parse_reply(server, &line) == 0) {
+ vstring_strcpy(reply, line);
+ return XSASL_AUTH_MORE;
+ }
+ } else if (strcmp(cmd, "FAIL") == 0) {
+ if (xsasl_dovecot_parse_reply(server, &line) == 0) {
+ /* authentication failure */
+ xsasl_dovecot_parse_reply_args(server, line, reply, 0);
+ return XSASL_AUTH_FAIL;
+ }
+ } else {
+ /* ignore */
+ }
+ }
+
+ vstring_strcpy(reply, "Connection lost to authentication server");
+ return XSASL_AUTH_FAIL;
+}
+
+/* is_valid_base64 - input sanitized */
+
+static int is_valid_base64(const char *data)
+{
+
+ /*
+ * XXX Maybe use ISALNUM() (isascii && isalnum, i.e. locale independent).
+ */
+ for (; *data != '\0'; data++) {
+ if (!((*data >= '0' && *data <= '9') ||
+ (*data >= 'a' && *data <= 'z') ||
+ (*data >= 'A' && *data <= 'Z') ||
+ *data == '+' || *data == '/' || *data == '='))
+ return 0;
+ }
+ return 1;
+}
+
+/* xsasl_dovecot_server_first - per-session authentication */
+
+int xsasl_dovecot_server_first(XSASL_SERVER *xp, const char *sasl_method,
+ const char *init_response, VSTRING *reply)
+{
+ char *myname = "xsasl_dovecot_server_first";
+ XSASL_DOVECOT_SERVER *server = (XSASL_DOVECOT_SERVER *) xp;
+ int i;
+
+#define IFELSE(e1,e2,e3) ((e1) ? (e2) : (e3))
+
+ if (msg_verbose)
+ msg_info("%s: sasl_method %s%s%s", myname, sasl_method,
+ IFELSE(init_response, ", init_response ", ""),
+ IFELSE(init_response, init_response, ""));
+
+ if (init_response)
+ if (!is_valid_base64(init_response)) {
+ vstring_strcpy(reply, "Invalid base64 data in initial response");
+ return XSASL_AUTH_FAIL;
+ }
+ for (i = 0; i < 2; i++) {
+ if (!server->impl->sasl_stream) {
+ if (xsasl_dovecot_server_connect(server->impl) < 0)
+ return (0);
+ }
+ /* send the request */
+ server->last_request_id = ++server->impl->request_id_counter;
+ vstream_fprintf(server->impl->sasl_stream,
+ "AUTH\t%u\t%s\tservice=%s",
+ server->last_request_id, sasl_method,
+ server->service);
+ if (init_response) {
+
+ /*
+ * initial response is already base64 encoded, so we can send it
+ * directly.
+ */
+ vstream_fprintf(server->impl->sasl_stream,
+ "\tresp=%s", init_response);
+ }
+ VSTREAM_PUTC('\n', server->impl->sasl_stream);
+
+ if (vstream_fflush(server->impl->sasl_stream) != VSTREAM_EOF)
+ break;
+
+ if (i == 1) {
+ vstring_strcpy(reply, "Can't connect to authentication server");
+ return XSASL_AUTH_FAIL;
+ }
+
+ /*
+ * Reconnect and try again.
+ */
+ xsasl_dovecot_server_disconnect(server->impl);
+ }
+
+ return xsasl_dovecot_handle_reply(server, reply);
+}
+
+/* xsasl_dovecot_server_next - continue authentication */
+
+static int xsasl_dovecot_server_next(XSASL_SERVER *xp, const char *request,
+ VSTRING *reply)
+{
+ XSASL_DOVECOT_SERVER *server = (XSASL_DOVECOT_SERVER *) xp;
+
+ if (!is_valid_base64(request)) {
+ vstring_strcpy(reply, "Invalid base64 data in continued response");
+ return XSASL_AUTH_FAIL;
+ }
+ vstream_fprintf(server->impl->sasl_stream,
+ "CONT\t%u\t%s\n", server->last_request_id, request);
+ if (vstream_fflush(server->impl->sasl_stream) == VSTREAM_EOF) {
+ vstring_strcpy(reply, "Connection lost to authentication server");
+ return XSASL_AUTH_FAIL;
+ }
+ return xsasl_dovecot_handle_reply(server, reply);
+}
+
+/* xsasl_dovecot_server_get_username - get authenticated username */
+
+static const char *xsasl_dovecot_server_get_username(XSASL_SERVER *xp)
+{
+ XSASL_DOVECOT_SERVER *server = (XSASL_DOVECOT_SERVER *) xp;
+
+ return (server->username);
+}
+
+#endif
#include <xsasl.h>
#include <xsasl_cyrus.h>
+#include <xsasl_dovecot.h>
/*
* Lookup table for available SASL server implementations.
static XSASL_SERVER_IMPL_INFO server_impl_info[] = {
#ifdef XSASL_TYPE_CYRUS
- XSASL_TYPE_CYRUS, xsasl_cyrus_server_init,
+ {XSASL_TYPE_CYRUS, xsasl_cyrus_server_init},
#endif
- 0,
+#ifdef XSASL_TYPE_DOVECOT
+ {XSASL_TYPE_DOVECOT, xsasl_dovecot_server_init},
+#endif
+ {0, 0}
};
/* xsasl_server_init - look up server implementation by name */