From: Wietse Venema Date: Thu, 22 Dec 2005 05:00:00 +0000 (-0500) Subject: postfix-2.3-20051222 X-Git-Tag: v2.3-RC1~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46ab025e8a85e7aab356334e17f198f6b74026ee;p=thirdparty%2Fpostfix.git postfix-2.3-20051222 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 785f16784..772688817 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -44,9 +44,6 @@ -TCRYPTO_EX_DATA -TCTABLE -TCTABLE_ENTRY --TXSASL_CYRUS_CLIENT --TXSASL_CYRUS_ERROR_INFO --TXSASL_CYRUS_SERVER -TDELIVER_ATTR -TDELIVER_REQUEST -TDELTA_TIME @@ -241,6 +238,11 @@ -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 diff --git a/postfix/HISTORY b/postfix/HISTORY index d11533737..1f6fbf838 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -11625,10 +11625,39 @@ Apologies for any names omitted. 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 diff --git a/postfix/README_FILES/SASL_README b/postfix/README_FILES/SASL_README index da0e31b7d..12ca1c6b3 100644 --- a/postfix/README_FILES/SASL_README +++ b/postfix/README_FILES/SASL_README @@ -28,9 +28,12 @@ search its SASL password table by the sender email address. 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 @@ -38,10 +41,45 @@ This document covers the following topics: WWhhaatt SSAASSLL vveerrssiioonnss aarree ssuuppppoorrtteedd -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. + +BBuuiillddiinngg PPoossttffiixx wwiitthh DDoovveeccoott SSAASSLL ssuuppppoorrtt + +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. BBuuiillddiinngg tthhee CCyyrruuss SSAASSLL lliibbrraarryy @@ -116,6 +154,36 @@ and later): Note: the SASL login names will be shared with the entire world. +DDoovveeccoott SSAASSLL ccoonnffiigguurraattiioonn ffoorr tthhee PPoossttffiixx SSMMTTPP sseerrvveerr + +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. + +CCyyrruuss SSAASSLL ccoonnffiigguurraattiioonn ffoorr tthhee PPoossttffiixx SSMMTTPP sseerrvveerr + 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. @@ -374,4 +442,6 @@ CCrreeddiittss 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. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index df9b5f944..0554a7089 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -17,6 +17,16 @@ Incompatibility with Postfix 2.1 and earlier 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 ====================================== diff --git a/postfix/html/SASL_README.html b/postfix/html/SASL_README.html index 4a720afc9..98b848f45 100644 --- a/postfix/html/SASL_README.html +++ b/postfix/html/SASL_README.html @@ -49,6 +49,9 @@ sender email address.

  • What SASL versions are supported +
  • Building Postfix with Dovecot SASL +support
  • +
  • Building the Cyrus SASL library
  • Building Postfix with Cyrus SASL @@ -57,6 +60,12 @@ 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
  • @@ -71,11 +80,66 @@ Postfix SMTP client

    What SASL versions are supported

    -

    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:

    + + + +

    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.

    + +

    Building Postfix with Dovecot SASL +support

    + +

    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:

    + +

    Building the Cyrus SASL library

    @@ -186,6 +250,48 @@ SMTP server

    Note: the SASL login names will be shared with the entire world.

    +

    Dovecot SASL configuration for the +Postfix SMTP server

    + +

    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.

    + +

    Cyrus SASL configuration for the Postfix +SMTP server

    +

    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.

    @@ -562,6 +668,9 @@ of SuSE Rhein/Main AG.
  • 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. + diff --git a/postfix/html/postconf.1.html b/postfix/html/postconf.1.html index 7e4de63d2..48139eb90 100644 --- a/postfix/html/postconf.1.html +++ b/postfix/html/postconf.1.html @@ -28,87 +28,99 @@ POSTCONF(1) POSTCONF(1) -a List the available SASL server plug-in types. The SASL plug-in type is selected with the - smtpd_sasl_type configuration parameter. + smtpd_sasl_type 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. - -A List the available SASL client plug-in types. The - SASL plug-in type is selected with the - smtp_sasl_type or lmtp_sasl_type configuration - parameters. + cyrus This server plug-in is available when Post- + fix is built with Cyrus SASL support. + + dovecot + This server plug-in requires the Dovecot + authentication server. + + -A List the available SASL client plug-in types. The + SASL plug-in type is selected with the + smtp_sasl_type or lmtp_sasl_type configuration + parameters by specifying one of the names listed + below. This feature is available with Postfix 2.3 and later. + cyrus This client plug-in is available when Post- + fix is built with Cyrus SASL support. + -b [template_file] Display the message text that appears at the begin- - ning of delivery status notification (DSN) mes- - sages, with $name 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 bounce_template_file 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 $name 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 bounce_template_file 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. -c config_dir - The main.cf configuration file is in the named + The main.cf configuration file is in the named directory instead of the default configuration directory. - -d Print default parameter settings instead of actual + -d Print default parameter settings instead of actual settings. - -e Edit the main.cf configuration file. The file is + -e Edit the main.cf 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. - -h Show parameter values only, not the ``name = '' + -h Show parameter values only, not the ``name = '' label that normally precedes the value. - -l List the names of all supported mailbox locking + -l List the names of all supported mailbox locking methods. Postfix supports the following methods: - flock A kernel-based advisory locking method for - local files only. This locking method is - available on systems with a BSD compatible + flock A kernel-based advisory locking method for + local files only. This locking method is + available on systems with a BSD compatible library. - fcntl A kernel-based advisory locking method for + fcntl A kernel-based advisory locking method for local and remote files. dotlock - An application-level locking method. An - application locks a file named filename by - creating a file named filename.lock. 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 filename by + creating a file named filename.lock. The + application is expected to remove its own + lock file, as well as stale lock files that were left behind after abnormal termination. -m List the names of all supported lookup table types. - In Postfix configuration files, lookup tables are - specified as type:name, where type is one of the - types listed below. The table name syntax depends - on the lookup table type as described in the DATA- + In Postfix configuration files, lookup tables are + specified as type:name, where type is one of the + types listed below. The table name syntax depends + on the lookup table type as described in the DATA- BASE_README document. - btree A sorted, balanced tree structure. This is + btree A sorted, balanced tree structure. This is available on systems with support for Berke- ley DB databases. - cdb A read-optimized structure with no support - for incremental updates. This is available + cdb A read-optimized structure with no support + for incremental updates. This is available on systems with support for CDB databases. - cidr A table that associates values with Class- - less Inter-Domain Routing (CIDR) patterns. + cidr A table that associates values with Class- + less Inter-Domain Routing (CIDR) patterns. This is described in cidr_table(5). dbm An indexed file type based on hashing. This @@ -117,75 +129,75 @@ POSTCONF(1) POSTCONF(1) environ 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. hash 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. ldap (read-only) - Perform lookups using the LDAP protocol. + Perform lookups using the LDAP protocol. This is described in ldap_table(5). mysql (read-only) - Perform lookups using the MYSQL protocol. + Perform lookups using the MYSQL protocol. This is described in mysql_table(5). pcre (read-only) A lookup table based on Perl Compatible Reg- - ular Expressions. The file format is + ular Expressions. The file format is described in pcre_table(5). pgsql (read-only) - Perform lookups using the PostgreSQL proto- + Perform lookups using the PostgreSQL proto- col. This is described in pgsql_table(5). proxy (read-only) - A lookup table that is implemented via the - Postfix proxymap(8) service. The table name + A lookup table that is implemented via the + Postfix proxymap(8) service. The table name syntax is type:name. regexp (read-only) A lookup table based on regular expressions. - The file format is described in regexp_ta- + The file format is described in regexp_ta- ble(5). sdbm An indexed file type based on hashing. This - is available on systems with support for + is available on systems with support for SDBM databases. static (read-only) - A table that always returns its name as - lookup result. For example, static:foobar - always returns the string foobar as lookup + A table that always returns its name as + lookup result. For example, static:foobar + always returns the string foobar as lookup result. tcp (read-only) Perform lookups using a simple request-reply - protocol that is described in tcp_table(5). - This feature is not included with Postfix + protocol that is described in tcp_table(5). + This feature is not included with Postfix 2.2. unix (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: unix:passwd.byname - 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 passwd(5) format. unix:group.byname The table is the UNIX group database. - The key is a group name. The result - is a group file entry in group(5) + The key is a group name. The result + is a group file entry in group(5) format. - Other table types may exist depending on how Post- + Other table types may exist depending on how Post- fix was built. -n Print parameter settings that are not left at their @@ -194,18 +206,18 @@ POSTCONF(1) POSTCONF(1) -t [template_file] 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 bounce_template_file parameter. To force - selection of the built-in templates, specify an + with the bounce_template_file 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. -v Enable verbose logging for debugging purposes. Mul- - tiple -v options make the software increasingly + tiple -v options make the software increasingly verbose. DIAGNOSTICS @@ -216,18 +228,18 @@ POSTCONF(1) POSTCONF(1) Directory with Postfix configuration files. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant + The following main.cf 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 postconf(5) for more details including examples. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and + The default location of the Postfix main.cf and master.cf configuration files. bounce_template_file (empty) - Pathname of a configuration file with bounce mes- + Pathname of a configuration file with bounce mes- sage templates. FILES @@ -241,7 +253,7 @@ POSTCONF(1) POSTCONF(1) DATABASE_README, Postfix lookup table overview LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 03a5ec6c3..eb78fb295 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -6047,6 +6047,17 @@ or to addresses that end in the "@" null domain, and from addresses that rewrite into a form that ends in the "@" null domain.

    + + +
    resolve_numeric_domain +(default: no)
    + +

    Resolve "user@ipaddress" as "user@[ipaddress]", instead of +rejecting the address as invalid.

    + +

    This feature is available in Postfix 2.3 and later. + +

    rewrite_service_name diff --git a/postfix/html/trivial-rewrite.8.html b/postfix/html/trivial-rewrite.8.html index 6f62be239..007e70dd7 100644 --- a/postfix/html/trivial-rewrite.8.html +++ b/postfix/html/trivial-rewrite.8.html @@ -102,24 +102,28 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) as if the local hostname were specified, instead of rejecting the address as invalid. + resolve_numeric_domain (no) + Resolve "user@ipaddress" as "user@[ipaddress]", + instead of rejecting the address as invalid. + ADDRESS REWRITING CONTROLS myorigin ($myhostname) 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. allow_percent_hack (yes) - Enable the rewriting of the form "user%domain" to + Enable the rewriting of the form "user%domain" to "user@domain". append_at_myorigin (yes) - With locally submitted mail, append the string - "@$myorigin" to mail addresses without domain + With locally submitted mail, append the string + "@$myorigin" to mail addresses without domain information. append_dot_mydomain (yes) - With locally submitted mail, append the string - ".$mydomain" to addresses that have no ".domain" + With locally submitted mail, append the string + ".$mydomain" to addresses that have no ".domain" information. recipient_delimiter (empty) @@ -127,75 +131,75 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) sions (user+foo). swap_bangpath (yes) - Enable the rewriting of "site!user" into + Enable the rewriting of "site!user" into "user@site". Available in Postfix 2.2 and later: remote_header_rewrite_domain (empty) - 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. ROUTING CONTROLS - The following is applicable to Postfix version 2.0 and - later. Earlier versions do not have support for: vir- - tual_transport, relay_transport, virtual_alias_domains, + The following is applicable to Postfix version 2.0 and + later. Earlier versions do not have support for: vir- + tual_transport, relay_transport, virtual_alias_domains, virtual_mailbox_domains or proxy_interfaces. local_transport (local:$myhostname) - The default mail delivery transport and next-hop - destination for final delivery to domains listed - with mydestination, and for [ipaddress] destina- - tions that match $inet_interfaces or $proxy_inter- + The default mail delivery transport and next-hop + destination for final delivery to domains listed + with mydestination, and for [ipaddress] destina- + tions that match $inet_interfaces or $proxy_inter- faces. virtual_transport (virtual) - 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 $virtual_mailbox_domains. relay_transport (relay) - 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 $relay_domains. default_transport (smtp) - 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 $mydestination, $inet_interfaces, $proxy_inter- faces, $virtual_alias_domains, $virtual_mail- box_domains, or $relay_domains. - parent_domain_matches_subdomains (see 'postconf -d' out- + parent_domain_matches_subdomains (see 'postconf -d' out- put) What Postfix features match subdomains of "domain.tld" automatically, instead of requiring an explicit ".domain.tld" pattern. relayhost (empty) - The next-hop destination of non-local mail; over- + The next-hop destination of non-local mail; over- rides non-local domains in recipient addresses. transport_maps (empty) 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: sender_dependent_relayhost_maps (empty) - A sender-dependent override for the global relay- + A sender-dependent override for the global relay- host parameter setting. ADDRESS VERIFICATION CONTROLS - 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: address_verify_local_transport ($local_transport) @@ -203,7 +207,7 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) address verification probes. address_verify_virtual_transport ($virtual_transport) - Overrides the virtual_transport parameter setting + Overrides the virtual_transport parameter setting for address verification probes. address_verify_relay_transport ($relay_transport) @@ -211,35 +215,35 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) address verification probes. address_verify_default_transport ($default_transport) - Overrides the default_transport parameter setting + Overrides the default_transport parameter setting for address verification probes. address_verify_relayhost ($relayhost) - Overrides the relayhost parameter setting for + Overrides the relayhost parameter setting for address verification probes. address_verify_transport_maps ($transport_maps) - Overrides the transport_maps parameter setting for + Overrides the transport_maps parameter setting for address verification probes. Available in Postfix version 2.3 and later: address_verify_sender_dependent_relayhost_maps (empty) Overrides the sender_dependent_relayhost_maps - parameter setting for address verification probes. + parameter setting for address verification probes. MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and + The default location of the Postfix main.cf and master.cf configuration files. daemon_timeout (18000s) - 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. empty_address_recipient (MAILER-DAEMON) - The recipient of mail addressed to the null + The recipient of mail addressed to the null address. ipc_timeout (3600s) @@ -247,12 +251,12 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) over an internal communication channel. max_idle (100s) - 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. max_use (100) - The maximal number of connection requests before a + The maximal number of connection requests before a Postfix daemon process terminates. relocated_maps (empty) @@ -260,33 +264,33 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) for users or domains that no longer exist. process_id (read-only) - The process ID of a Postfix command or daemon + The process ID of a Postfix command or daemon process. process_name (read-only) - The process name of a Postfix command or daemon + The process name of a Postfix command or daemon process. queue_directory (see 'postconf -d' output) - The location of the Postfix top-level queue direc- + The location of the Postfix top-level queue direc- tory. show_user_unknown_table_name (yes) - Display the name of the recipient table in the + Display the name of the recipient table in the "User unknown" responses. syslog_facility (mail) The syslog facility of Postfix logging. syslog_name (postfix) - 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: helpful_warnings (yes) - Log warnings about problematic configuration set- + Log warnings about problematic configuration set- tings, and provide helpful suggestions. SEE ALSO @@ -301,7 +305,7 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) ADDRESS_VERIFICATION_README, Postfix address verification LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/man/man1/postconf.1 b/postfix/man/man1/postconf.1 index 1b982d816..06d43b7f7 100644 --- a/postfix/man/man1/postconf.1 +++ b/postfix/man/man1/postconf.1 @@ -30,15 +30,30 @@ Options: .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 diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 97247d18b..192116ec4 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -3362,6 +3362,11 @@ hostname. 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, diff --git a/postfix/man/man8/trivial-rewrite.8 b/postfix/man/man8/trivial-rewrite.8 index b7123ee50..396147f95 100644 --- a/postfix/man/man8/trivial-rewrite.8 +++ b/postfix/man/man8/trivial-rewrite.8 @@ -105,6 +105,9 @@ looking inside quotes. 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 diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index d57349ca9..830173962 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -371,6 +371,7 @@ while (<>) { s;\brelay_destination_concurrency_limit\b;$&;g; s;\brelay_destination_recip[-]*\n* *[]*ient_limit\b;$&;g; s;\bresolve_null_domain\b;$&;g; + s;\bresolve_numeric_domain\b;$&;g; s;\bsmtp_destination_concurrency_limit\b;$&;g; s;\bsmtp_destination_recip[-]*\n* *[]*ient_limit\b;$&;g; s;\bvir[-]*\n*[ ]*tual_destination_concurrency_limit\b;$&;g; diff --git a/postfix/proto/SASL_README.html b/postfix/proto/SASL_README.html index 90da1ee6e..a651a1ac8 100644 --- a/postfix/proto/SASL_README.html +++ b/postfix/proto/SASL_README.html @@ -49,6 +49,9 @@ sender email address.

  • What SASL versions are supported +
  • Building Postfix with Dovecot SASL +support
  • +
  • Building the Cyrus SASL library
  • Building Postfix with Cyrus SASL @@ -57,6 +60,12 @@ 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
  • @@ -71,11 +80,66 @@ Postfix SMTP client
  • What SASL versions are supported

    -

    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:

    + + + +

    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.

    + +

    Building Postfix with Dovecot SASL +support

    + +

    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:

    + +

    Building the Cyrus SASL library

    @@ -186,6 +250,48 @@ SMTP server

    Note: the SASL login names will be shared with the entire world.

    +

    Dovecot SASL configuration for the +Postfix SMTP server

    + +

    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.

    + +

    Cyrus SASL configuration for the Postfix +SMTP server

    +

    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.

    @@ -562,6 +668,9 @@ 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. + diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index cc4786893..3bcaa68b2 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -9116,3 +9116,10 @@ is rejected by the reject_plaintext_session restriction.

    This feature is available in Postfix 2.3 and later.

    + +%PARAM resolve_numeric_domain no + +

    Resolve "user@ipaddress" as "user@[ipaddress]", instead of +rejecting the address as invalid.

    + +

    This feature is available in Postfix 2.3 and later. diff --git a/postfix/src/dns/dns.h b/postfix/src/dns/dns.h index e84ce8abc..415c4703b 100644 --- a/postfix/src/dns/dns.h +++ b/postfix/src/dns/dns.h @@ -81,6 +81,7 @@ typedef struct DNS_FIXED { */ 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 */ @@ -104,7 +105,8 @@ extern unsigned dns_type(const char *); /* * 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 *); diff --git a/postfix/src/dns/dns_lookup.c b/postfix/src/dns/dns_lookup.c index 573994769..5ec5b8fe4 100644 --- a/postfix/src/dns/dns_lookup.c +++ b/postfix/src/dns/dns_lookup.c @@ -349,8 +349,9 @@ static int valid_rr_name(const char *name, const char *location, /* 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; @@ -423,8 +424,8 @@ static int dns_get_rr(DNS_RR **list, DNS_REPLY *reply, unsigned char *pos, *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); } @@ -444,7 +445,7 @@ static int dns_get_alias(DNS_REPLY *reply, unsigned char *pos, /* 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]; @@ -518,7 +519,8 @@ static int dns_get_answer(DNS_REPLY *reply, int type, 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) @@ -556,6 +558,7 @@ int dns_lookup(const char *name, unsigned type, unsigned flags, static DNS_REPLY reply; int count; int status; + const char *orig_name = name; /* * DJBDNS produces a bogus A record when given a numerical hostname. @@ -597,7 +600,8 @@ int dns_lookup(const char *name, unsigned type, unsigned flags, * 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) diff --git a/postfix/src/dns/dns_rr.c b/postfix/src/dns/dns_rr.c index 0063a201e..e4dc0f85e 100644 --- a/postfix/src/dns/dns_rr.c +++ b/postfix/src/dns/dns_rr.c @@ -6,9 +6,10 @@ /* SYNOPSIS /* #include /* -/* 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; @@ -45,7 +46,8 @@ /* 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. @@ -98,7 +100,8 @@ /* 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) { @@ -106,6 +109,7 @@ DNS_RR *dns_rr_create(const char *name, ushort type, ushort class, 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; @@ -125,6 +129,7 @@ void dns_rr_free(DNS_RR *rr) if (rr->next) dns_rr_free(rr->next); myfree(rr->name); + myfree(rr->rname); myfree((char *) rr); } } @@ -142,6 +147,7 @@ DNS_RR *dns_rr_copy(DNS_RR *src) 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); } diff --git a/postfix/src/dns/dns_sa_to_rr.c b/postfix/src/dns/dns_sa_to_rr.c index da8aa9e1d..d8a8dc94c 100644 --- a/postfix/src/dns/dns_sa_to_rr.c +++ b/postfix/src/dns/dns_sa_to_rr.c @@ -54,12 +54,12 @@ DNS_RR *dns_sa_to_rr(const char *hostname, unsigned pref, struct sockaddr * sa) #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 diff --git a/postfix/src/dns/test_dns_lookup.c b/postfix/src/dns/test_dns_lookup.c index e1350fd75..ac61287ac 100644 --- a/postfix/src/dns/test_dns_lookup.c +++ b/postfix/src/dns/test_dns_lookup.c @@ -45,7 +45,7 @@ static void print_rr(DNS_RR *rr) 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 diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 2decd4cef..685bf2647 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1926,11 +1926,11 @@ extern int var_fflush_refresh; * 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; /* @@ -2124,6 +2124,10 @@ extern bool var_resolve_dequoted; #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 diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 70e7badf7..ede017197 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * 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 diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c index be948313f..ad1c2a726 100644 --- a/postfix/src/postconf/postconf.c +++ b/postfix/src/postconf/postconf.c @@ -24,15 +24,30 @@ /* .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 diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index ec1f60385..9cf948c3f 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -2484,7 +2484,7 @@ static int check_server_access(SMTPD_STATE *state, const char *table, (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) { @@ -3301,13 +3301,13 @@ static int check_policy_service(SMTPD_STATE *state, const char *server, 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. */ diff --git a/postfix/src/trivial-rewrite/resolve.c b/postfix/src/trivial-rewrite/resolve.c index 2ba518da9..f961b0111 100644 --- a/postfix/src/trivial-rewrite/resolve.c +++ b/postfix/src/trivial-rewrite/resolve.c @@ -366,9 +366,20 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr, */ 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; diff --git a/postfix/src/trivial-rewrite/trivial-rewrite.c b/postfix/src/trivial-rewrite/trivial-rewrite.c index 0ab6f46dc..9852dea32 100644 --- a/postfix/src/trivial-rewrite/trivial-rewrite.c +++ b/postfix/src/trivial-rewrite/trivial-rewrite.c @@ -87,6 +87,9 @@ /* 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 @@ -311,6 +314,7 @@ int var_show_unk_rcpt_table; int var_resolve_nulldom; char *var_remote_rwr_domain; char *var_snd_relay_maps; +int var_resolve_num_dom; /* * Shadow personality for address verification. @@ -557,6 +561,7 @@ int main(int argc, char **argv) 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, }; diff --git a/postfix/src/util/sys_defs.h b/postfix/src/util/sys_defs.h index 17d7968cf..366521091 100644 --- a/postfix/src/util/sys_defs.h +++ b/postfix/src/util/sys_defs.h @@ -1322,12 +1322,12 @@ typedef int pid_t; #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)) @@ -1340,21 +1340,6 @@ typedef int pid_t; #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 diff --git a/postfix/src/util/unescape.c b/postfix/src/util/unescape.c index 14be31fa6..27d9d849f 100644 --- a/postfix/src/util/unescape.c +++ b/postfix/src/util/unescape.c @@ -144,29 +144,32 @@ VSTRING *escape(VSTRING *result, const char *data, ssize_t len) 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); @@ -175,16 +178,29 @@ VSTRING *escape(VSTRING *result, const char *data, ssize_t len) #ifdef TEST #include +#include +#include #include -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); diff --git a/postfix/src/util/vstring.c b/postfix/src/util/vstring.c index b73983b36..c050f6381 100644 --- a/postfix/src/util/vstring.c +++ b/postfix/src/util/vstring.c @@ -81,6 +81,12 @@ /* 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; @@ -208,6 +214,10 @@ /* /* 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. /* @@ -477,6 +487,34 @@ char *vstring_memchr(VSTRING *vp, int ch) 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) diff --git a/postfix/src/util/vstring.h b/postfix/src/util/vstring.h index e031bbcf8..30b463d1e 100644 --- a/postfix/src/util/vstring.h +++ b/postfix/src/util/vstring.h @@ -41,6 +41,7 @@ extern VSTRING *vstring_strncat(VSTRING *, const char *, ssize_t); 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 *,...); diff --git a/postfix/src/xsasl/Makefile.in b/postfix/src/xsasl/Makefile.in index 0e45a12fe..2a2d51c0b 100644 --- a/postfix/src/xsasl/Makefile.in +++ b/postfix/src/xsasl/Makefile.in @@ -1,8 +1,10 @@ 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) @@ -118,6 +120,22 @@ xsasl_cyrus_server.o: xsasl.h 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 @@ -127,4 +145,5 @@ xsasl_server.o: ../../include/vstream.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 diff --git a/postfix/src/xsasl/xsasl_dovecot.h b/postfix/src/xsasl/xsasl_dovecot.h new file mode 100644 index 000000000..f99850e92 --- /dev/null +++ b/postfix/src/xsasl/xsasl_dovecot.h @@ -0,0 +1,41 @@ +#ifndef _XSASL_DOVECOT_H_INCLUDED_ +#define _XSASL_DOVECOT_H_INCLUDED_ + +/*++ +/* NAME +/* xsasl_dovecot 3h +/* SUMMARY +/* Dovecot SASL plug-in +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * XSASL library. + */ +#include + +#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 diff --git a/postfix/src/xsasl/xsasl_dovecot_server.c b/postfix/src/xsasl/xsasl_dovecot_server.c new file mode 100644 index 000000000..af2f0cedb --- /dev/null +++ b/postfix/src/xsasl/xsasl_dovecot_server.c @@ -0,0 +1,496 @@ +/*++ +/* 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 +#include +#include +#include + +/* Utility library. */ + +#include +#include +#include +#include +#include +#include +#include + +/* Global library. */ + +#include + +/* Application-specific. */ + +#include +#include + +#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 diff --git a/postfix/src/xsasl/xsasl_server.c b/postfix/src/xsasl/xsasl_server.c index 729cb46e6..23531cd4a 100644 --- a/postfix/src/xsasl/xsasl_server.c +++ b/postfix/src/xsasl/xsasl_server.c @@ -185,6 +185,7 @@ #include #include +#include /* * Lookup table for available SASL server implementations. @@ -196,9 +197,12 @@ typedef struct { 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 */