From: Wietse Venema Date: Fri, 11 May 2007 05:00:00 +0000 (-0500) Subject: postfix-2.5-20070511 X-Git-Tag: v2.5.0-RC1~44 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=df417a866b8e0a88725917a1198f961537a18f6f;p=thirdparty%2Fpostfix.git postfix-2.5-20070511 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index f590fce21..7fde1b246 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -254,6 +254,7 @@ -TXSASL_CYRUS_CLIENT -TXSASL_CYRUS_ERROR_INFO -TXSASL_CYRUS_SERVER +-TXSASL_DCSRV_MECH -TXSASL_DOVECOT_SERVER -TXSASL_DOVECOT_SERVER_IMPL -TXSASL_DOVECOT_SERVER_MECHS diff --git a/postfix/HISTORY b/postfix/HISTORY index 528ce0fd3..ed883f525 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -13514,8 +13514,35 @@ Apologies for any names omitted. from localhost[127.0.0.1]. Files: smtpd/smtpd_peer.c, qmqpd/qmqpd_peer.c. +20070502 + + Workaround: build without EPOLL support when an epoll-enabled + kernel sits underneath a retarded libc. File: makedefs. + + Cleanup: missing support for SASL security properties with + Dovecot SASL authentication. Based on an initial version + by Lev A. Serebryakov. File: xsasl/xsasl_dovecot_server.c. + +20070503 + + Cleanup: changed the default address verification sender + from "postmaster" to "double-bounce", so that the Postfix + SMTP server no longer surprises unsuspecting people by + excluding "postmaster" from SMTPD access controls. File: + global/mail_params.h. + +20070508 + + Bugfix: Content-Transfer-Encoding: attribute values are + case insensitive. File: src/cleanup/cleanup_message.c. + + Wish list: + Would there be a problem adding $smtpd_mumble_restrictions + and $smtpd_sender_login_maps to the default proxy_read_maps + settings? + Remove defer(8) and trace(8) references and man pages. These are services not program names. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 543da6e99..085400686 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -17,6 +17,14 @@ Incompatibility with Postfix 2.3 and earlier If you upgrade from Postfix 2.3 or earlier, read RELEASE_NOTES-2.4 before proceeding. +Incompatibility with Postfix snapshot 2007XXXX +============================================== + +The default sender address for address verification probes was +changed from "postmaster" to "double-bounce", so that the Postfix +SMTP server no longer causes surprising behavior by excluding +"postmaster" from SMTP server access controls. + Incompatibility with Postfix snapshot 20070422 ============================================== diff --git a/postfix/html/cidr_table.5.html b/postfix/html/cidr_table.5.html index fb721fd02..09689d910 100644 --- a/postfix/html/cidr_table.5.html +++ b/postfix/html/cidr_table.5.html @@ -90,6 +90,9 @@ CIDR_TABLE(5) CIDR_TABLE(5) README FILES DATABASE_README, Postfix lookup table overview +HISTORY + CIDR table support was introduced with Postfix version 2.1. + AUTHOR(S) The CIDR table lookup code was originally written by: Jozsef Kadlecsik diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index cd9cde335..c1fbb218b 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -344,9 +344,10 @@ This feature is available in Postfix 2.1 and later.
address_verify_sender -(default: postmaster)
+(default: $double_bounce_sender)
-

The sender address to use in address verification probes. To +

The sender address to use in address verification probes; prior +to Postfix 2.5 the default was "postmaster". To avoid problems with address probes that are sent in response to address probes, the Postfix SMTP server excludes the probe sender address from all SMTPD access blocks.

@@ -10566,10 +10567,15 @@ Specify zero or more of the following:
Disallow methods that allow anonymous authentication.
+
forward_secrecy
+ +
Only allow methods that support forward secrecy (Dovecot only). +
+
mutual_auth
Only allow methods that provide mutual authentication (not available -with SASL version 1).
+with Cyrus SASL version 1). diff --git a/postfix/html/postsuper.1.html b/postfix/html/postsuper.1.html index 44c6e6e46..2445c4865 100644 --- a/postfix/html/postsuper.1.html +++ b/postfix/html/postsuper.1.html @@ -101,23 +101,27 @@ POSTSUPER(1) POSTSUPER(1) ting. It becomes subject to expiration after it is released from "hold". + This feature is available in Postfix 2.0 and later. + -H queue_id Release mail that was put "on hold". Move one mes- - sage with the named queue ID from the named mail + sage with the named queue ID from the named mail queue(s) (default: hold) to the deferred queue. - If a queue_id of - is specified, the program reads + If a queue_id of - is specified, the program reads queue IDs from standard input. - Note: specify "postsuper -r" to release mail that - was kept on hold for a significant fraction of - $maximal_queue_lifetime or $bounce_queue_lifetime, + Note: specify "postsuper -r" to release mail that + was kept on hold for a significant fraction of + $maximal_queue_lifetime or $bounce_queue_lifetime, or longer. - Specify "-H ALL" to release all mail that is "on - hold". As a safety measure, the word ALL must be + Specify "-H ALL" to release all mail that is "on + hold". As a safety measure, the word ALL must be specified in upper case. + This feature is available in Postfix 2.0 and later. + -p Purge old temporary files that are left over after system or software crashes. @@ -168,33 +172,35 @@ POSTSUPER(1) POSTSUPER(1) the Postfix mail system is running, but no harm should be done. - -s Structure check and structure repair. This should + This feature is available in Postfix 1.1 and later. + + -s Structure check and structure repair. This should be done once before Postfix startup. - o Rename files whose name does not match the + o Rename files whose name does not match the message file inode number. This operation is - necessary after restoring a mail queue from + necessary after restoring a mail queue from a different machine, or from backup media. o Move queue files that are in the wrong place in the file system hierarchy and remove sub- directories that are no longer needed. File - position rearrangements are necessary after + position rearrangements are necessary after a change in the hash_queue_names and/or hash_queue_depth configuration parameters. -v Enable verbose logging for debugging purposes. Mul- - tiple -v options make the software increasingly + tiple -v options make the software increasingly verbose. DIAGNOSTICS - Problems are reported to the standard error stream and to + Problems are reported to the standard error stream and to syslogd(8). - postsuper(1) reports the number of messages deleted with - -d, the number of messages requeued with -r, and the num- - ber of messages whose queue file name was fixed with -s. - The report is written to the standard error stream and to + postsuper(1) reports the number of messages deleted with + -d, the number of messages requeued with -r, and the num- + ber of messages whose queue file name was fixed with -s. + The report is written to the standard error stream and to syslogd(8). ENVIRONMENT @@ -202,37 +208,37 @@ POSTSUPER(1) POSTSUPER(1) Directory with the main.cf file. BUGS - Mail that is not sanitized by Postfix (i.e. mail in the + Mail that is not sanitized by Postfix (i.e. mail in the maildrop queue) cannot be placed "on hold". 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 postconf(5) for more details including exam- + summary. See postconf(5) for more details including exam- ples. 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. hash_queue_depth (1) - The number of subdirectory levels for queue direc- - tories listed with the hash_queue_names parameter. + The number of subdirectory levels for queue direc- + tories listed with the hash_queue_names parameter. hash_queue_names (deferred, defer) - The names of queue directories that are split + The names of queue directories that are split across multiple subdirectory levels. 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. 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". SEE ALSO @@ -240,7 +246,7 @@ POSTSUPER(1) POSTSUPER(1) postqueue(1), unprivileged queue operations 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/makedefs b/postfix/makedefs index 3a6842861..befbbd600 100644 --- a/postfix/makedefs +++ b/postfix/makedefs @@ -282,6 +282,32 @@ case "$SYSTEM.$RELEASE" in case "$RELEASE" in 2.[0-5].*) CCARGS="$CCARGS -DNO_EPOLL";; esac + # Workaround for retarded libc + case "$RELEASE" in + 2.6.*) + trap 'rm -f makedefs.tmp makedefs.tmp.o makedefs.tmp.c' 1 2 3 15 + cat >makedefs.tmp.c < +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int epoll_handle; + + if ((epoll_handle = epoll_create(1)) < 0) { + perror("epoll_create"); + exit(1); + } + exit(0); +} +EOF + ${CC-gcc} -o makedefs.tmp makedefs.tmp.c || exit 1 + ./makedefs.tmp 2>/dev/null || CCARGS="$CCARGS -DNO_EPOLL" + rm -f makedefs.tmp makedefs.tmp.o makedefs.tmp.c;; + esac ;; GNU.0*|GNU/kFreeBSD.[56]*) SYSTYPE=GNU0 diff --git a/postfix/man/man1/postsuper.1 b/postfix/man/man1/postsuper.1 index 2564d60d8..c38dc8f9d 100644 --- a/postfix/man/man1/postsuper.1 +++ b/postfix/man/man1/postsuper.1 @@ -94,6 +94,8 @@ Note: while mail is "on hold" it will not expire when its time in the queue exceeds the \fBmaximal_queue_lifetime\fR or \fBbounce_queue_lifetime\fR setting. It becomes subject to expiration after it is released from "hold". +.sp +This feature is available in Postfix 2.0 and later. .IP "\fB-H \fIqueue_id\fR" Release mail that was put "on hold". Move one message with the named queue ID from the named @@ -109,6 +111,8 @@ or \fB$bounce_queue_lifetime\fR, or longer. Specify "\fB-H ALL\fR" to release all mail that is "on hold". As a safety measure, the word \fBALL\fR must be specified in upper case. +.sp +This feature is available in Postfix 2.0 and later. .IP \fB-p\fR Purge old temporary files that are left over after system or software crashes. @@ -154,6 +158,8 @@ Warning: Postfix queue IDs are reused. There is a very small possibility that \fBpostsuper\fR(1) requeues the wrong message file when it is executed while the Postfix mail system is running, but no harm should be done. +.sp +This feature is available in Postfix 1.1 and later. .IP \fB-s\fR Structure check and structure repair. This should be done once before Postfix startup. diff --git a/postfix/man/man5/cidr_table.5 b/postfix/man/man5/cidr_table.5 index 8790e4725..f25ab45cd 100644 --- a/postfix/man/man5/cidr_table.5 +++ b/postfix/man/man5/cidr_table.5 @@ -96,6 +96,10 @@ Use "\fBpostconf readme_directory\fR" or .na .nf DATABASE_README, Postfix lookup table overview +.SH "HISTORY" +.na +.nf +CIDR table support was introduced with Postfix version 2.1. .SH "AUTHOR(S)" .na .nf diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 62a6d11a7..1d3dfac0a 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -175,8 +175,9 @@ Overrides the relayhost parameter setting for address verification probes. This information can be overruled with the \fBtransport\fR(5) table. .PP This feature is available in Postfix 2.1 and later. -.SH address_verify_sender (default: postmaster) -The sender address to use in address verification probes. To +.SH address_verify_sender (default: $double_bounce_sender) +The sender address to use in address verification probes; prior +to Postfix 2.5 the default was "postmaster". To avoid problems with address probes that are sent in response to address probes, the Postfix SMTP server excludes the probe sender address from all SMTPD access blocks. @@ -6312,9 +6313,11 @@ Disallow methods subject to active (non-dictionary) attack. Disallow methods subject to passive (dictionary) attack. .IP "\fBnoanonymous\fR" Disallow methods that allow anonymous authentication. +.IP "\fBforward_secrecy\fR" +Only allow methods that support forward secrecy (Dovecot only). .IP "\fBmutual_auth\fR" Only allow methods that provide mutual authentication (not available -with SASL version 1). +with Cyrus SASL version 1). .PP By default, the Postfix SMTP server accepts plaintext passwords but not anonymous logins. diff --git a/postfix/proto/cidr_table b/postfix/proto/cidr_table index 20df979e9..4a24d0531 100644 --- a/postfix/proto/cidr_table +++ b/postfix/proto/cidr_table @@ -80,6 +80,8 @@ # .na # .nf # DATABASE_README, Postfix lookup table overview +# HISTORY +# CIDR table support was introduced with Postfix version 2.1. # AUTHOR(S) # The CIDR table lookup code was originally written by: # Jozsef Kadlecsik diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 7054b3181..1f613d6f4 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -340,9 +340,10 @@ probes. This information can be overruled with the transport(5) table. This feature is available in Postfix 2.1 and later.

-%PARAM address_verify_sender postmaster +%PARAM address_verify_sender $double_bounce_sender -

The sender address to use in address verification probes. To +

The sender address to use in address verification probes; prior +to Postfix 2.5 the default was "postmaster". To avoid problems with address probes that are sent in response to address probes, the Postfix SMTP server excludes the probe sender address from all SMTPD access blocks.

@@ -5561,10 +5562,15 @@ Specify zero or more of the following:
Disallow methods that allow anonymous authentication.
+
forward_secrecy
+ +
Only allow methods that support forward secrecy (Dovecot only). +
+
mutual_auth
Only allow methods that provide mutual authentication (not available -with SASL version 1).
+with Cyrus SASL version 1). diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index 61ac63425..fee73bbe9 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -512,11 +512,11 @@ static void cleanup_header_callback(void *context, int header_class, while (ISSPACE(*hdrval)) hdrval++; /* trimblanks(hdrval, 0)[0] = 0; */ - if (var_auto_8bit_enc_hdr + if (var_auto_8bit_enc_hdr && hdr_opts->type == HDR_CONTENT_TRANSFER_ENCODING) { for (cmp = code_map; cmp->name != 0; cmp++) { if (strcasecmp(hdrval, cmp->name) == 0) { - if (strcmp(cmp->encoding, MAIL_ATTR_ENC_8BIT) == 0) + if (strcasecmp(cmp->encoding, MAIL_ATTR_ENC_8BIT) == 0) nvtable_update(state->attr, MAIL_ATTR_ENCODING, cmp->encoding); break; diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 9c70bfd85..54995c2e4 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -2363,7 +2363,7 @@ extern int var_verify_neg_try; extern bool var_verify_neg_cache; #define VAR_VERIFY_SENDER "address_verify_sender" -#define DEF_VERIFY_SENDER "postmaster" +#define DEF_VERIFY_SENDER "$" VAR_DOUBLE_BOUNCE extern char *var_verify_sender; #define VAR_VERIFY_POLL_COUNT "address_verify_poll_count" diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index bf2c5a497..b54eb5879 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 "20070501" +#define MAIL_RELEASE_DATE "20070511" #define MAIL_VERSION_NUMBER "2.5" #ifdef SNAPSHOT diff --git a/postfix/src/global/resolve_clnt.c b/postfix/src/global/resolve_clnt.c index 4668deadd..bbd1b9b3a 100644 --- a/postfix/src/global/resolve_clnt.c +++ b/postfix/src/global/resolve_clnt.c @@ -191,7 +191,7 @@ void resolve_clnt(const char *class, const char *sender, */ #define IFSET(flag, text) ((reply->flags & (flag)) ? (text) : "") - if (event_time() < last_expire + if (time((time_t *) 0) < last_expire && *addr && strcmp(addr, STR(last_addr)) == 0 && strcmp(class, STR(last_class)) == 0 && strcmp(sender, STR(last_sender)) == 0) { @@ -284,7 +284,7 @@ void resolve_clnt(const char *class, const char *sender, vstring_strcpy(last_reply.nexthop, STR(reply->nexthop)); vstring_strcpy(last_reply.recipient, STR(reply->recipient)); last_reply.flags = reply->flags; - last_expire = event_time() + 30; /* XXX make configurable */ + last_expire = time((time_t *) 0) + 30; /* XXX make configurable */ } /* resolve_clnt_free - destroy reply */ diff --git a/postfix/src/global/rewrite_clnt.c b/postfix/src/global/rewrite_clnt.c index 6d110bf59..43b892a25 100644 --- a/postfix/src/global/rewrite_clnt.c +++ b/postfix/src/global/rewrite_clnt.c @@ -108,7 +108,7 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result) /* * Peek at the cache. */ - if (event_time() < last_expire + if (time((time_t *) 0) < last_expire && strcmp(addr, STR(last_addr)) == 0 && strcmp(rule, STR(last_rule)) == 0) { vstring_strcpy(result, STR(last_result)); @@ -165,7 +165,7 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result) vstring_strcpy(last_rule, rule); vstring_strcpy(last_addr, addr); vstring_strcpy(last_result, STR(result)); - last_expire = event_time() + 30; /* XXX make configurable */ + last_expire = time((time_t *) 0) + 30; /* XXX make configurable */ return (result); } diff --git a/postfix/src/postsuper/postsuper.c b/postfix/src/postsuper/postsuper.c index 65172d08a..48f390909 100644 --- a/postfix/src/postsuper/postsuper.c +++ b/postfix/src/postsuper/postsuper.c @@ -88,6 +88,8 @@ /* time in the queue exceeds the \fBmaximal_queue_lifetime\fR /* or \fBbounce_queue_lifetime\fR setting. It becomes subject to /* expiration after it is released from "hold". +/* .sp +/* This feature is available in Postfix 2.0 and later. /* .IP "\fB-H \fIqueue_id\fR" /* Release mail that was put "on hold". /* Move one message with the named queue ID from the named @@ -103,6 +105,8 @@ /* Specify "\fB-H ALL\fR" to release all mail that is "on hold". /* As a safety measure, the word \fBALL\fR must be specified in upper /* case. +/* .sp +/* This feature is available in Postfix 2.0 and later. /* .IP \fB-p\fR /* Purge old temporary files that are left over after system or /* software crashes. @@ -148,6 +152,8 @@ /* There is a very small possibility that \fBpostsuper\fR(1) requeues /* the wrong message file when it is executed while the Postfix mail /* system is running, but no harm should be done. +/* .sp +/* This feature is available in Postfix 1.1 and later. /* .IP \fB-s\fR /* Structure check and structure repair. This should be done once /* before Postfix startup. diff --git a/postfix/src/trivial-rewrite/trivial-rewrite.c b/postfix/src/trivial-rewrite/trivial-rewrite.c index d539a5d2a..fd315a201 100644 --- a/postfix/src/trivial-rewrite/trivial-rewrite.c +++ b/postfix/src/trivial-rewrite/trivial-rewrite.c @@ -364,7 +364,7 @@ RES_CONTEXT resolve_verify = { * This code detaches the trivial-rewrite process from the master, stops * accepting new clients, and handles established clients in the background, * asking them to reconnect the next time they send a request. The master - * create a new process that accepts connections. This is reasonably safe + * creates a new process that accepts connections. This is reasonably safe * because the number of trivial-rewrite server processes is small compared * to the number of trivial-rewrite client processes. The few extra * background processes should not make a difference in Postfix's footprint. diff --git a/postfix/src/xsasl/xsasl_cyrus_client.c b/postfix/src/xsasl/xsasl_cyrus_client.c index 4e525e031..e38ab380d 100644 --- a/postfix/src/xsasl/xsasl_cyrus_client.c +++ b/postfix/src/xsasl/xsasl_cyrus_client.c @@ -337,7 +337,7 @@ XSASL_CLIENT *xsasl_cyrus_client_create(XSASL_CLIENT_IMPL *unused_impl, } /* - * Extend XSASL_CLIENT_IMPL object with our own state. We use long-lived + * Extend the XSASL_CLIENT object with our own state. We use long-lived * conversion buffers rather than local variables to avoid memory leaks * in case of read/write timeout or I/O error. * diff --git a/postfix/src/xsasl/xsasl_cyrus_server.c b/postfix/src/xsasl/xsasl_cyrus_server.c index 3a2db98f4..69f2fba0d 100644 --- a/postfix/src/xsasl/xsasl_cyrus_server.c +++ b/postfix/src/xsasl/xsasl_cyrus_server.c @@ -311,9 +311,9 @@ static XSASL_SERVER *xsasl_cyrus_server_create(XSASL_SERVER_IMPL *unused_impl, } /* - * 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. + * Extend the XSASL_SERVER 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_CYRUS_SERVER *) mymalloc(sizeof(*server)); server->xsasl.free = xsasl_cyrus_server_free; diff --git a/postfix/src/xsasl/xsasl_dovecot_server.c b/postfix/src/xsasl/xsasl_dovecot_server.c index c20e3da47..fa59fa722 100644 --- a/postfix/src/xsasl/xsasl_dovecot_server.c +++ b/postfix/src/xsasl/xsasl_dovecot_server.c @@ -59,6 +59,7 @@ #include #include #include +#include /* Global library. */ @@ -82,14 +83,63 @@ */ #define AUTH_TIMEOUT 10 + /* + * Security property bitmasks. + */ +#define SEC_PROPS_NOPLAINTEXT (1 << 0) +#define SEC_PROPS_NOACTIVE (1 << 1) +#define SEC_PROPS_NODICTIONARY (1 << 2) +#define SEC_PROPS_NOANONYMOUS (1 << 3) +#define SEC_PROPS_FWD_SECRECY (1 << 4) +#define SEC_PROPS_MUTUAL_AUTH (1 << 5) +#define SEC_PROPS_PRIVATE (1 << 6) + +#define SEC_PROPS_POS_MASK (SEC_PROPS_MUTUAL_AUTH | SEC_PROPS_FWD_SECRECY) +#define SEC_PROPS_NEG_MASK (SEC_PROPS_NOPLAINTEXT | SEC_PROPS_NOACTIVE | \ + SEC_PROPS_NODICTIONARY | SEC_PROPS_NOANONYMOUS) + + /* + * Security properties as specified in the Postfix main.cf file. + */ +static NAME_MASK xsasl_dovecot_conf_sec_props[] = { + "noplaintext", SEC_PROPS_NOPLAINTEXT, + "noactive", SEC_PROPS_NOACTIVE, + "nodictionary", SEC_PROPS_NODICTIONARY, + "noanonymous", SEC_PROPS_NOANONYMOUS, + "forward_secrecy", SEC_PROPS_FWD_SECRECY, + "mutual_auth", SEC_PROPS_MUTUAL_AUTH, + 0, 0, +}; + + /* + * Security properties as specified in the Dovecot protocol. See + * http://wiki.dovecot.org/Authentication_Protocol. + */ +static NAME_MASK xsasl_dovecot_serv_sec_props[] = { + "plaintext", SEC_PROPS_NOPLAINTEXT, + "active", SEC_PROPS_NOACTIVE, + "dictionary", SEC_PROPS_NODICTIONARY, + "anonymous", SEC_PROPS_NOANONYMOUS, + "forward-secrecy", SEC_PROPS_FWD_SECRECY, + "mutual-auth", SEC_PROPS_MUTUAL_AUTH, + "private", SEC_PROPS_PRIVATE, + 0, 0, +}; + /* * Class variables. */ +typedef struct XSASL_DCSRV_MECH { + char *mech_name; /* mechanism name */ + int sec_props; /* mechanism properties */ + struct XSASL_DCSRV_MECH *next; +} XSASL_DCSRV_MECH; + typedef struct { XSASL_SERVER_IMPL xsasl; VSTREAM *sasl_stream; char *socket_path; - char *mechanism_list; /* applicable mechanisms */ + XSASL_DCSRV_MECH *mechanism_list; /* unfiltered mechanism list */ unsigned int request_id_counter; } XSASL_DOVECOT_SERVER_IMPL; @@ -104,6 +154,8 @@ typedef struct { char *service; char *username; /* authenticated user */ VSTRING *sasl_line; + unsigned int sec_props; /* Postfix mechanism filter */ + char *mechanism_list; /* filtered mechanism list */ } XSASL_DOVECOT_SERVER; /* @@ -122,16 +174,79 @@ 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 *); +/* xsasl_dovecot_server_mech_append - append server mechanism entry */ + +static void xsasl_dovecot_server_mech_append(XSASL_DCSRV_MECH **mech_list, + const char *mech_name, int sec_props) +{ + XSASL_DCSRV_MECH **mpp; + XSASL_DCSRV_MECH *mp; + + for (mpp = mech_list; *mpp != 0; mpp = &mpp[0]->next) + /* void */ ; + + mp = (XSASL_DCSRV_MECH *) mymalloc(sizeof(*mp)); + mp->mech_name = mystrdup(mech_name); + mp->sec_props = sec_props; + mp->next = 0; + *mpp = mp; +} + +/* xsasl_dovecot_server_mech_free - destroy server mechanism list */ + +static void xsasl_dovecot_server_mech_free(XSASL_DCSRV_MECH *mech_list) +{ + XSASL_DCSRV_MECH *mp; + XSASL_DCSRV_MECH *next; + + for (mp = mech_list; mp != 0; mp = next) { + myfree(mp->mech_name); + next = mp->next; + myfree((char *) mp); + } +} + +/* xsasl_dovecot_server_mech_filter - filter server mechanism list */ + +static char *xsasl_dovecot_server_mech_filter(XSASL_DCSRV_MECH *mechanism_list, + unsigned int conf_props) +{ + const char *myname = "xsasl_dovecot_server_mech_filter"; + unsigned int pos_conf_props = (conf_props & SEC_PROPS_POS_MASK); + unsigned int neg_conf_props = (conf_props & SEC_PROPS_NEG_MASK); + VSTRING *mechanisms_str = vstring_alloc(10); + XSASL_DCSRV_MECH *mp; + + /* + * Match Postfix properties against Dovecot server properties. + */ + for (mp = mechanism_list; mp != 0; mp = mp->next) { + if ((mp->sec_props & pos_conf_props) == pos_conf_props + && (mp->sec_props & neg_conf_props) == 0) { + if (VSTRING_LEN(mechanisms_str) > 0) + VSTRING_ADDCH(mechanisms_str, ' '); + vstring_strcat(mechanisms_str, mp->mech_name); + if (msg_verbose) + msg_info("%s: keep mechanism: %s", myname, mp->mech_name); + } else { + if (msg_verbose) + msg_info("%s: skip mechanism: %s", myname, mp->mech_name); + } + } + return (vstring_export(mechanisms_str)); +} + /* xsasl_dovecot_server_connect - initial auth server handshake */ static int xsasl_dovecot_server_connect(XSASL_DOVECOT_SERVER_IMPL *xp) { const char *myname = "xsasl_dovecot_server_connect"; - VSTRING *line_str, *mechanisms_str; + VSTRING *line_str; VSTREAM *sasl_stream; char *line, *cmd, *mech_name; unsigned int major_version, minor_version; int fd, success; + int sec_props; if (msg_verbose) msg_info("%s: Connecting", myname); @@ -158,7 +273,6 @@ static int xsasl_dovecot_server_connect(XSASL_DOVECOT_SERVER_IMPL *xp) } 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); @@ -182,10 +296,17 @@ static int xsasl_dovecot_server_connect(XSASL_DOVECOT_SERVER_IMPL *xp) } 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); + if (line != 0) { + sec_props = + name_mask_delim_opt(myname, + xsasl_dovecot_serv_sec_props, + line, "\t", NAME_MASK_ANY_CASE); + if ((sec_props & SEC_PROPS_PRIVATE) != 0) + continue; + } else + sec_props = 0; + xsasl_dovecot_server_mech_append(&xp->mechanism_list, mech_name, + sec_props); } else if (strcmp(cmd, "DONE") == 0) { /* Handshake finished. */ success = 1; @@ -198,15 +319,10 @@ static int xsasl_dovecot_server_connect(XSASL_DOVECOT_SERVER_IMPL *xp) 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); } @@ -219,7 +335,7 @@ static void xsasl_dovecot_server_disconnect(XSASL_DOVECOT_SERVER_IMPL *xp) xp->sasl_stream = 0; } if (xp->mechanism_list) { - myfree(xp->mechanism_list); + xsasl_dovecot_server_mech_free(xp->mechanism_list); xp->mechanism_list = 0; } } @@ -258,7 +374,7 @@ 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 *sec_props) { const char *myname = "xsasl_dovecot_server_create"; XSASL_DOVECOT_SERVER *server; @@ -283,6 +399,10 @@ static XSASL_SERVER *xsasl_dovecot_server_create(XSASL_SERVER_IMPL *impl, server->username = 0; server->service = mystrdup(service); server->last_request_id = 0; + server->mechanism_list = 0; + server->sec_props = + name_mask_opt(myname, xsasl_dovecot_conf_sec_props, + sec_props, NAME_MASK_ANY_CASE | NAME_MASK_FATAL); return (&server->xsasl); } @@ -297,7 +417,11 @@ static const char *xsasl_dovecot_server_get_mechanism_list(XSASL_SERVER *xp) if (xsasl_dovecot_server_connect(server->impl) < 0) return (0); } - return (server->impl->mechanism_list); + if (server->mechanism_list == 0) + server->mechanism_list = + xsasl_dovecot_server_mech_filter(server->impl->mechanism_list, + server->sec_props); + return (server->mechanism_list[0] ? server->mechanism_list : 0); } /* xsasl_dovecot_server_free - destroy server instance */ @@ -309,6 +433,8 @@ static void xsasl_dovecot_server_free(XSASL_SERVER *xp) vstring_free(server->sasl_line); if (server->username) myfree(server->username); + if (server->mechanism_list) + myfree(server->mechanism_list); myfree(server->service); myfree((char *) server); }