From: Wietse Venema
With "-o disable_mime_output_conversion=yes", the scan -delivery agent will not convert 8BITMIME mail to quoted-printable -form while delivering to the content filter, as that would invalidate -domainkeys and other digital signatures. This workaround is needed -because some SMTP-based content filters don't announce 8BITMIME -support, even though they can handle it just fine.
+The "-o disable_mime_output_conversion=yes" is a workaround +that prevents the breaking of domainkeys and other digital signatures. +This is needed because some SMTP-based content filters don't announce +8BITMIME support, even though they can handle it just fine.
diff --git a/postfix/html/MILTER_README.html b/postfix/html/MILTER_README.html index 1ae1d0676..9f8a5151b 100644 --- a/postfix/html/MILTER_README.html +++ b/postfix/html/MILTER_README.html @@ -613,9 +613,9 @@ TOContent filters may break domain key etc. signatures. If you -use an SMTP-based filter as described in FILTER_README, then you -should add a line to master.cf with "disable_mime_output_conversion -= yes", as described in the master.cf with "-o disable_mime_output_conversion=yes" (note: no +spaces around the "="), as described in the advanced content filter example.
diff --git a/postfix/html/SASL_README.html b/postfix/html/SASL_README.html index d177f7f15..3086d14e4 100644 --- a/postfix/html/SASL_README.html +++ b/postfix/html/SASL_README.html @@ -127,7 +127,7 @@ in the Postfix top-level directory:@@ -138,7 +138,7 @@ in the Postfix top-level directory:-% make makefiles CCARGS='-DUSE_SASL_AUTH -DDEF_SASL_SERVER=\"dovecot\"' +% make makefiles CCARGS='-DUSE_SASL_AUTH -DDEF_SASL_SERVER_TYPE=\"dovecot\"'
The "-DDEF_SASL_SERVER" stuff is not necessary; it just +
The "-DDEF_SASL_SERVER_TYPE" 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.
diff --git a/postfix/html/TLS_README.html b/postfix/html/TLS_README.html index 42ed35f78..b3f30dadd 100644 --- a/postfix/html/TLS_README.html +++ b/postfix/html/TLS_README.html @@ -490,8 +490,9 @@ and OE (5.01 Mac on all ports).It is strictly discouraged to use this mode from main.cf. If you want to support this service, enable a special port in master.cf -and specify "-o smtpd_tls_wrappermode = yes" as an smtpd(8) command -line option. Port 465 (smtps) was once chosen for this feature. +and specify "-o smtpd_tls_wrappermode=yes" (note: no space around +the "=") as an smtpd(8) command line option. Port 465 (smtps) was +once chosen for this feature.
Example:
@@ -631,6 +632,22 @@ recommends a maximum of 24 hours. +When the Postfix SMTP server does not save TLS sessions to an +external cache database, client-side session caching is unlikely +to be useful. To prevent such wastage, the Postfix SMTP server can +be configured to not issue TLS session ids. By default the Postfix +SMTP server always issues TLS session ids. This works around known +interoperability issues with some MUAs, and prevents possible +interoperability issues with other MTAs.
+ +Example:
+ ++++ smtpd_tls_always_issue_session_ids = no ++
Postfix TLS support introduces three additional features for diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 0600eabab..b485dc1d8 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -3556,17 +3556,6 @@ Enable SASL authentication in the Postfix LMTP client.
- - -The LMTP-specific version of the smtp_sasl_auth_enforce -configuration parameter. See there for details.
- -This feature is available in Postfix 2.3 and later.
- -If sender-dependent SASL passwords are turned off, defer mail -delivery when an SMTP server does not support SASL authentication, -while smtp_sasl_password_maps contains SASL login/password information -for that server.
- -This feature is available in Postfix 2.3 and later.
- -Attempt to look up the Postfix SMTP client hostname, and verify that +
Attempt to look up the remote SMTP client hostname, and verify that the name matches the client IP address. A client name is set to "unknown" when it cannot be looked up or verified, or when name lookup is disabled. Turning off name lookup reduces delays due to @@ -10780,6 +10756,36 @@ feature is therefore not recommended.
This feature is available in Postfix 2.2 and later.
+Force the Postfix SMTP server to issue a TLS session id, even +when TLS session caching is turned off (smtpd_tls_session_cache_database +is empty). This behavior is compatible with Postfix < 2.3.
+ +With Postfix 2.3 and later the Postfix SMTP server can disable +session id generation when TLS session caching is turned off. This +keeps clients from caching sessions that almost certainly cannot +be re-used.
+ +By default, the Postfix SMTP server always generates TLS session +ids. This works around a known defect in mail client applications +such as MS Outlook, and may also prevent interoperability issues +with other MTAs.
+ +Example:
+ +++ ++ smtpd_tls_always_issue_session_ids = no ++
This feature is available in Postfix 2.3 and later.
+ +With "-o disable_mime_output_conversion=yes", the scan -delivery agent will not convert 8BITMIME mail to quoted-printable -form while delivering to the content filter, as that would invalidate -domainkeys and other digital signatures. This workaround is needed -because some SMTP-based content filters don't announce 8BITMIME -support, even though they can handle it just fine.
+The "-o disable_mime_output_conversion=yes" is a workaround +that prevents the breaking of domainkeys and other digital signatures. +This is needed because some SMTP-based content filters don't announce +8BITMIME support, even though they can handle it just fine.
diff --git a/postfix/proto/MILTER_README.html b/postfix/proto/MILTER_README.html index 8e56061f2..7005e0986 100644 --- a/postfix/proto/MILTER_README.html +++ b/postfix/proto/MILTER_README.html @@ -613,9 +613,9 @@ TOContent filters may break domain key etc. signatures. If you -use an SMTP-based filter as described in FILTER_README, then you -should add a line to master.cf with "disable_mime_output_conversion -= yes", as described in the advanced content filter example.
diff --git a/postfix/proto/SASL_README.html b/postfix/proto/SASL_README.html index 2c0ac06c1..cd6d23ab1 100644 --- a/postfix/proto/SASL_README.html +++ b/postfix/proto/SASL_README.html @@ -127,7 +127,7 @@ in the Postfix top-level directory:@@ -138,7 +138,7 @@ INSTALL document.-% make makefiles CCARGS='-DUSE_SASL_AUTH -DDEF_SASL_SERVER=\"dovecot\"' +% make makefiles CCARGS='-DUSE_SASL_AUTH -DDEF_SASL_SERVER_TYPE=\"dovecot\"'
The "-DDEF_SASL_SERVER" stuff is not necessary; it just +
The "-DDEF_SASL_SERVER_TYPE" 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.
diff --git a/postfix/proto/TLS_README.html b/postfix/proto/TLS_README.html index 249e3b22c..7247efedc 100644 --- a/postfix/proto/TLS_README.html +++ b/postfix/proto/TLS_README.html @@ -490,8 +490,9 @@ and OE (5.01 Mac on all ports).It is strictly discouraged to use this mode from main.cf. If you want to support this service, enable a special port in master.cf -and specify "-o smtpd_tls_wrappermode = yes" as an smtpd(8) command -line option. Port 465 (smtps) was once chosen for this feature. +and specify "-o smtpd_tls_wrappermode=yes" (note: no space around +the "=") as an smtpd(8) command line option. Port 465 (smtps) was +once chosen for this feature.
Example:
@@ -631,6 +632,22 @@ recommends a maximum of 24 hours. +When the Postfix SMTP server does not save TLS sessions to an +external cache database, client-side session caching is unlikely +to be useful. To prevent such wastage, the Postfix SMTP server can +be configured to not issue TLS session ids. By default the Postfix +SMTP server always issues TLS session ids. This works around known +interoperability issues with some MUAs, and prevents possible +interoperability issues with other MTAs.
+ +Example:
+ ++++ smtpd_tls_always_issue_session_ids = no ++
Postfix TLS support introduces three additional features for diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index f233c4662..0918f8db9 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -8941,7 +8941,7 @@ process instance while mail is being forwarded.
%PARAM smtpd_peername_lookup yes -Attempt to look up the Postfix SMTP client hostname, and verify that +
Attempt to look up the remote SMTP client hostname, and verify that the name matches the client IP address. A client name is set to "unknown" when it cannot be looked up or verified, or when name lookup is disabled. Turning off name lookup reduces delays due to @@ -10367,22 +10367,6 @@ configuration parameter. See there for details.
This feature is available in Postfix 2.3 and later.
-%PARAM smtp_sasl_auth_enforce yes - -If sender-dependent SASL passwords are turned off, defer mail -delivery when an SMTP server does not support SASL authentication, -while smtp_sasl_password_maps contains SASL login/password information -for that server.
- -This feature is available in Postfix 2.3 and later.
- -%PARAM lmtp_sasl_auth_enforce yes - -The LMTP-specific version of the smtp_sasl_auth_enforce -configuration parameter. See there for details.
- -This feature is available in Postfix 2.3 and later.
- %PARAM smtpd_tls_security_levelThe SMTP TLS security level for the Postfix SMTP server; when @@ -10444,3 +10428,29 @@ notifications by the smtp(8) and smtpd(8) processes. Postfix-generated email messages. The user is warned.
This feature is available in Postfix 2.3 and later.
+ +%PARAM smtpd_tls_always_issue_session_ids yes + +Force the Postfix SMTP server to issue a TLS session id, even +when TLS session caching is turned off (smtpd_tls_session_cache_database +is empty). This behavior is compatible with Postfix < 2.3.
+ +With Postfix 2.3 and later the Postfix SMTP server can disable +session id generation when TLS session caching is turned off. This +keeps clients from caching sessions that almost certainly cannot +be re-used.
+ +By default, the Postfix SMTP server always generates TLS session +ids. This works around a known defect in mail client applications +such as MS Outlook, and may also prevent interoperability issues +with other MTAs.
+ +Example:
+ +++ ++ smtpd_tls_always_issue_session_ids = no ++
This feature is available in Postfix 2.3 and later.
diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index cc0a9bd51..c3b5dd612 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -92,6 +92,8 @@ typedef struct CLEANUP_STATE { MILTERS *milters; /* mail filters */ const char *client_name; /* real or ersatz client */ const char *client_addr; /* real or ersatz client */ + int client_af; /* real or ersatz client */ + const char *client_port; /* real or ersatz client */ } CLEANUP_STATE; /* diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c index ebd1f5ce7..beacd8249 100644 --- a/postfix/src/cleanup/cleanup_milter.c +++ b/postfix/src/cleanup/cleanup_milter.c @@ -1277,6 +1277,12 @@ static const char *cleanup_milter_apply(CLEANUP_STATE *state, const char *event, if (msg_verbose) msg_info("%s: %s", myname, resp); + /* + * Sanity check. + */ + if (state->client_name == 0) + msg_panic("%s: missing client info initialization", myname); + /* * We don't report errors that were already reported by the content * editing call-back routines. See cleanup_milter_error() above. @@ -1354,6 +1360,34 @@ static const char *cleanup_milter_apply(CLEANUP_STATE *state, const char *event, return (ret); } +/* cleanup_milter_client_init - initialize real or ersatz client info */ + +static void cleanup_milter_client_init(CLEANUP_STATE *state) +{ + const char *proto_attr; + + /* + * Either the cleanup client specifies a name, address and protocol, or + * we have a local submission and pretend localhost/127.0.0.1/AF_INET. + */ +#define NO_CLIENT_PORT "0" + + state->client_name = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_NAME); + state->client_addr = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_ADDR); + state->client_port = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_PORT); + proto_attr = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_AF); + + if (state->client_name == 0 || state->client_addr == 0 || proto_attr == 0 + || !alldig(proto_attr)) { + state->client_name = "localhost"; + state->client_addr = "127.0.0.1"; + state->client_af = AF_INET; + } else + state->client_af = atoi(proto_attr); + if (state->client_port == 0) + state->client_port = NO_CLIENT_PORT; +} + /* cleanup_milter_inspect - run message through mail filter */ void cleanup_milter_inspect(CLEANUP_STATE *state, MILTERS *milters) @@ -1364,6 +1398,12 @@ void cleanup_milter_inspect(CLEANUP_STATE *state, MILTERS *milters) if (msg_verbose) msg_info("enter %s", myname); + /* + * Initialize, in case we're called via smtpd(8). + */ + if (state->client_name == 0) + cleanup_milter_client_init(state); + /* * Process mail filter replies. The reply format is verified by the mail * filter library. @@ -1382,9 +1422,6 @@ void cleanup_milter_emul_mail(CLEANUP_STATE *state, const char *addr) { const char *resp; - const char *proto_attr; - const char *client_port; - int client_af; const char *helo; const char *argv[2]; @@ -1397,33 +1434,14 @@ void cleanup_milter_emul_mail(CLEANUP_STATE *state, cleanup_ins_header, cleanup_del_header, cleanup_add_rcpt, cleanup_del_rcpt, cleanup_repl_body, (void *) state); - - /* - * Either the cleanup client specifies a name, address and protocol, or - * we have a local submission and pretend localhost/127.0.0.1/AF_INET. - */ -#define NO_CLIENT_PORT "0" - - state->client_name = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_NAME); - state->client_addr = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_ADDR); - - client_port = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_PORT); - proto_attr = nvtable_find(state->attr, MAIL_ATTR_ACT_CLIENT_AF); - if (state->client_name == 0 || state->client_addr == 0 || proto_attr == 0 - || !alldig(proto_attr)) { - state->client_name = "localhost"; - state->client_addr = "127.0.0.1"; - client_af = AF_INET; - } else - client_af = atoi(proto_attr); - if (client_port == 0) - client_port = NO_CLIENT_PORT; + if (state->client_name == 0) + cleanup_milter_client_init(state); /* * Emulate SMTP events. */ if ((resp = milter_conn_event(milters, state->client_name, state->client_addr, - client_port, client_af)) != 0) { + state->client_port, state->client_af)) != 0) { cleanup_milter_apply(state, "CONNECT", resp); return; } @@ -1453,9 +1471,16 @@ void cleanup_milter_emul_rcpt(CLEANUP_STATE *state, MILTERS *milters, const char *addr) { + const char *myname = "cleanup_milter_emul_rcpt"; const char *resp; const char *argv[2]; + /* + * Sanity check. + */ + if (state->client_name == 0) + msg_panic("%s: missing client info initialization", myname); + /* * CLEANUP_STAT_CONT and CLEANUP_STAT_DEFER both update the reason * attribute, but CLEANUP_STAT_DEFER takes precedence. It terminates @@ -1479,8 +1504,15 @@ void cleanup_milter_emul_rcpt(CLEANUP_STATE *state, void cleanup_milter_emul_data(CLEANUP_STATE *state, MILTERS *milters) { + const char *myname = "cleanup_milter_emul_data"; const char *resp; + /* + * Sanity check. + */ + if (state->client_name == 0) + msg_panic("%s: missing client info initialization", myname); + if ((resp = milter_data_event(milters)) != 0) cleanup_milter_apply(state, "DATA", resp); } diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c index fae7fdd58..d1fc37203 100644 --- a/postfix/src/cleanup/cleanup_state.c +++ b/postfix/src/cleanup/cleanup_state.c @@ -110,6 +110,8 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src) state->milters = 0; state->client_name = 0; state->client_addr = 0; + state->client_af = 0; + state->client_port = 0; return (state); } diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 5ab4dbf55..082a4a126 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1183,6 +1183,10 @@ extern char *var_smtpd_tls_scache_db; #define DEF_SMTPD_TLS_SCACHTIME "3600s" extern int var_smtpd_tls_scache_timeout; +#define VAR_SMTPD_TLS_SET_SESSID "smtpd_tls_always_issue_session_ids" +#define DEF_SMTPD_TLS_SET_SESSID 1 +extern bool var_smtpd_tls_set_sessid; + #define VAR_SMTPD_DELAY_OPEN "smtpd_delay_open_until_valid_rcpt" #define DEF_SMTPD_DELAY_OPEN 1 extern bool var_smtpd_delay_open; diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 99c4bfc5a..edd0ad650 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 "20060711" +#define MAIL_RELEASE_DATE "20060719" #define MAIL_VERSION_NUMBER "2.4" #ifdef SNAPSHOT diff --git a/postfix/src/milter/test-list b/postfix/src/milter/test-list index f66a0ac39..70ea9a4c5 100644 --- a/postfix/src/milter/test-list +++ b/postfix/src/milter/test-list @@ -1,3 +1,13 @@ +# Reject with text +./test-milter -C 1 -a "554 5.7.1 Rejected" -c connect -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 Rejected" -c helo -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 Rejected" -c mail -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 Rejected" -c rcpt -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 Rejected" -c header -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 Rejected" -c eoh -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 Rejected" -c body -p inet:9999@127.0.0.1 +./test-milter -C 1 -a "554 5.7.1 Rejected" -c eom -p inet:9999@127.0.0.1 + # Tempfail tests ./test-milter -C 1 -a tempfail -c connect -p inet:9999@127.0.0.1 ./test-milter -C 1 -a tempfail -c helo -p inet:9999@127.0.0.1 diff --git a/postfix/src/milter/test-milter.c b/postfix/src/milter/test-milter.c index f11962a44..d617499d3 100644 --- a/postfix/src/milter/test-milter.c +++ b/postfix/src/milter/test-milter.c @@ -96,17 +96,23 @@ static char *reply_code; static char *reply_dsn; static char *reply_message; +#ifdef SMFIR_INSHEADER static char *ins_hdr; static int ins_idx; static char *ins_val; +#endif + +#ifdef SMFIR_CHGHEADER static char *chg_hdr; static int chg_idx; static char *chg_val; +#endif + static int test_reply(SMFICTX *ctx, int code) { - (void) fflush(stdout); /* In case output redirected. */ + (void) fflush(stdout); /* In case output redirected. */ if (code == SMFIR_REPLYCODE) { if (smfi_setreply(ctx, reply_code, reply_dsn, reply_message) != MI_SUCCESS) @@ -214,10 +220,14 @@ static sfsistat test_body(SMFICTX *ctx, unsigned char *data, size_t data_len) static sfsistat test_eom(SMFICTX *ctx) { printf("test_eom\n"); +#ifdef SMFIR_INSHEADER if (ins_hdr && smfi_insheader(ctx, ins_idx, ins_hdr, ins_val) == MI_FAILURE) fprintf(stderr, "smfi_insheader failed"); +#endif +#ifdef SMFIR_CHGHEADER if (chg_hdr && smfi_chgheader(ctx, chg_hdr, chg_idx, chg_val) == MI_FAILURE) fprintf(stderr, "smfi_chgheader failed"); +#endif return (test_reply(ctx, test_eom_reply)); } @@ -318,6 +328,7 @@ int main(int argc, char **argv) exit(1); } break; +#ifdef SMFIR_INSHEADER case 'i': if (ins_hdr) { fprintf(stderr, "too many -i options\n"); @@ -325,12 +336,14 @@ int main(int argc, char **argv) } parse_hdr_info(optarg, &ins_idx, &ins_hdr, &ins_val); break; +#endif case 'p': if (smfi_setconn(optarg) == MI_FAILURE) { fprintf(stderr, "smfi_setconn failed\n"); exit(1); } break; +#ifdef SMFIR_CHGHEADER case 'r': if (chg_hdr) { fprintf(stderr, "too many -r options\n"); @@ -338,6 +351,7 @@ int main(int argc, char **argv) } parse_hdr_info(optarg, &chg_idx, &chg_hdr, &chg_val); break; +#endif case 'v': verbose++; break; diff --git a/postfix/src/postfix/postfix.c b/postfix/src/postfix/postfix.c index bad094a78..784526c47 100644 --- a/postfix/src/postfix/postfix.c +++ b/postfix/src/postfix/postfix.c @@ -239,6 +239,14 @@ /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* +/* TLS support by: +/* Lutz Jaenicke +/* Brandenburg University of Technology +/* Cottbus, Germany +/* +/* Victor Duchovni +/* Morgan Stanley +/* /* SASL support originally by: /* Till Franke /* SuSE Rhein/Main AG diff --git a/postfix/src/smtp/lmtp_params.c b/postfix/src/smtp/lmtp_params.c index fa488781e..e5f0c119c 100644 --- a/postfix/src/smtp/lmtp_params.c +++ b/postfix/src/smtp/lmtp_params.c @@ -95,6 +95,5 @@ #endif VAR_LMTP_SENDER_AUTH, DEF_LMTP_SENDER_AUTH, &var_smtp_sender_auth, VAR_LMTP_CNAME_OVERR, DEF_LMTP_CNAME_OVERR, &var_smtp_cname_overr, - VAR_LMTP_SASL_ENFORCE, DEF_LMTP_SASL_ENFORCE, &var_smtp_sasl_enforce, 0, }; diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index 7fdbf780d..b6fdad8b0 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -234,11 +234,6 @@ /* server's list of offered SASL mechanisms. /* .PP /* Available in Postfix version 2.3 and later: -/* .IP "\fBsmtp_sasl_auth_enforce (yes)\fR" -/* If sender-dependent SASL passwords are turned off, defer mail -/* delivery when an SMTP server does not support SASL authentication, -/* while smtp_sasl_password_maps contains SASL login/password information -/* for that server. /* .IP "\fBsmtp_sender_dependent_authentication (no)\fR" /* Enable sender-dependent authentication in the Postfix SMTP client; this is /* available only with SASL authentication, and disables SMTP connection @@ -297,6 +292,13 @@ /* .IP "\fBsmtp_tls_note_starttls_offer (no)\fR" /* Log the hostname of a remote SMTP server that offers STARTTLS, /* when TLS is not already enabled for that server. +/* .IP "\fBsmtp_tls_policy_maps (empty)\fR" +/* Optional lookup tables with the Postfix SMTP client TLS security +/* policy by next-hop destination; when a non-empty value is specified, +/* this overrides the obsolete smtp_tls_per_site parameter. +/* .IP "\fBsmtp_tls_mandatory_protocols (SSLv3, TLSv1)\fR" +/* List of TLS protocols that the Postfix SMTP client will use +/* with mandatory TLS encryption. /* .IP "\fBsmtp_tls_scert_verifydepth (5)\fR" /* The verification depth for remote SMTP server certificates. /* .IP "\fBsmtp_tls_secure_cert_match (nexthop, dot-nexthop)\fR" @@ -697,7 +699,6 @@ bool var_smtp_sender_auth; char *var_lmtp_tcp_port; int var_scache_proto_tmout; bool var_smtp_cname_overr; -bool var_smtp_sasl_enforce; /* * Global variables. diff --git a/postfix/src/smtp/smtp_params.c b/postfix/src/smtp/smtp_params.c index 540da3781..9c73b2d58 100644 --- a/postfix/src/smtp/smtp_params.c +++ b/postfix/src/smtp/smtp_params.c @@ -99,6 +99,5 @@ #endif VAR_SMTP_SENDER_AUTH, DEF_SMTP_SENDER_AUTH, &var_smtp_sender_auth, VAR_SMTP_CNAME_OVERR, DEF_SMTP_CNAME_OVERR, &var_smtp_cname_overr, - VAR_SMTP_SASL_ENFORCE, DEF_SMTP_SASL_ENFORCE, &var_smtp_sasl_enforce, 0, }; diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index b66d91a9f..7fb0c262f 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -359,7 +359,6 @@ int smtp_helo(SMTP_STATE *state) "host %s refused to talk to me: %s", session->namaddr, translit(resp->str, "\n", " "))); - return (0); } } else { where = "performing the LHLO handshake"; @@ -372,93 +371,106 @@ int smtp_helo(SMTP_STATE *state) } /* - * Determine what server EHLO keywords to ignore, typically to avoid - * inter-operability problems. + * No early returns allowed, to ensure consistent handling of TLS and + * SASL policies. */ - if (smtp_ehlo_dis_maps == 0 - || (ehlo_words = maps_find(smtp_ehlo_dis_maps, state->session->addr, 0)) == 0) - ehlo_words = var_smtp_ehlo_dis_words; - discard_mask = ehlo_mask(ehlo_words); - if (discard_mask && !(discard_mask & EHLO_MASK_SILENT)) - msg_info("discarding EHLO keywords: %s", str_ehlo_mask(discard_mask)); + if (session->features & SMTP_FEATURE_ESMTP) { - /* - * Pick up some useful features offered by the SMTP server. XXX Until we - * have a portable routine to convert from string to off_t with proper - * overflow detection, ignore the message size limit advertised by the - * SMTP server. Otherwise, we might do the wrong thing when the server - * advertises a really huge message size limit. - * - * XXX Allow for "code (SP|-) ehlo-keyword (SP|=) ehlo-param...", because - * MicroSoft implemented AUTH based on an old draft. - */ - lines = resp->str; - for (n = 0; (words = mystrtok(&lines, "\n")) != 0; /* see below */ ) { - if (mystrtok(&words, "- ") && (word = mystrtok(&words, " \t=")) != 0) { - if (n == 0) { - if (session->helo != 0) - myfree(session->helo); + /* + * Determine what server EHLO keywords to ignore, typically to avoid + * inter-operability problems. + */ + if (smtp_ehlo_dis_maps == 0 + || (ehlo_words = maps_find(smtp_ehlo_dis_maps, + state->session->addr, 0)) == 0) + ehlo_words = var_smtp_ehlo_dis_words; + discard_mask = ehlo_mask(ehlo_words); + if (discard_mask && !(discard_mask & EHLO_MASK_SILENT)) + msg_info("discarding EHLO keywords: %s", + str_ehlo_mask(discard_mask)); - /* - * XXX: Keep the original case: we don't expect a single SMTP - * server to randomly change the case of its helo response. - * If different capitalization is detected, we should assume - * disjoint TLS caches. - */ - session->helo = mystrdup(word); - if (strcasecmp(word, var_myhostname) == 0 - && (state->misc_flags & SMTP_MISC_FLAG_LOOP_DETECT) != 0) { - msg_warn("host %s replied to HELO/EHLO with my own hostname %s", - session->namaddrport, var_myhostname); - if (session->features & SMTP_FEATURE_BEST_MX) - return (smtp_site_fail(state, DSN_BY_LOCAL_MTA, + /* + * Pick up some useful features offered by the SMTP server. XXX Until + * we have a portable routine to convert from string to off_t with + * proper overflow detection, ignore the message size limit + * advertised by the SMTP server. Otherwise, we might do the wrong + * thing when the server advertises a really huge message size limit. + * + * XXX Allow for "code (SP|-) ehlo-keyword (SP|=) ehlo-param...", + * because MicroSoft implemented AUTH based on an old draft. + */ + lines = resp->str; + for (n = 0; (words = mystrtok(&lines, "\n")) != 0; /* see below */ ) { + if (mystrtok(&words, "- ") + && (word = mystrtok(&words, " \t=")) != 0) { + if (n == 0) { + if (session->helo != 0) + myfree(session->helo); + + /* + * XXX: Keep the original case: we don't expect a single + * SMTP server to randomly change the case of its helo + * response. If different capitalization is detected, we + * should assume disjoint TLS caches. + */ + session->helo = mystrdup(word); + if (strcasecmp(word, var_myhostname) == 0 + && (state->misc_flags & SMTP_MISC_FLAG_LOOP_DETECT) != 0) { + msg_warn("host %s replied to HELO/EHLO" + " with my own hostname %s", + session->namaddrport, var_myhostname); + if (session->features & SMTP_FEATURE_BEST_MX) + return (smtp_site_fail(state, DSN_BY_LOCAL_MTA, SMTP_RESP_FAKE(&fake, "5.4.6"), "mail for %s loops back to myself", - request->nexthop)); - else - return (smtp_site_fail(state, DSN_BY_LOCAL_MTA, + request->nexthop)); + else + return (smtp_site_fail(state, DSN_BY_LOCAL_MTA, SMTP_RESP_FAKE(&fake, "4.4.6"), "mail for %s loops back to myself", - request->nexthop)); - } - } else if (strcasecmp(word, "8BITMIME") == 0) { - if ((discard_mask & EHLO_MASK_8BITMIME) == 0) - session->features |= SMTP_FEATURE_8BITMIME; - } else if (strcasecmp(word, "PIPELINING") == 0) { - if ((discard_mask & EHLO_MASK_PIPELINING) == 0) - session->features |= SMTP_FEATURE_PIPELINING; - } else if (strcasecmp(word, "XFORWARD") == 0) { - if ((discard_mask & EHLO_MASK_XFORWARD) == 0) - while ((word = mystrtok(&words, " \t")) != 0) - session->features |= name_code(xforward_features, - NAME_CODE_FLAG_NONE, word); - } else if (strcasecmp(word, "SIZE") == 0) { - if ((discard_mask & EHLO_MASK_SIZE) == 0) { - session->features |= SMTP_FEATURE_SIZE; - if ((word = mystrtok(&words, " \t")) != 0) { - if (!alldig(word)) - msg_warn("bad EHLO SIZE limit \"%s\" from %s", - word, session->namaddrport); - else - session->size_limit = off_cvt_string(word); + request->nexthop)); + } + } else if (strcasecmp(word, "8BITMIME") == 0) { + if ((discard_mask & EHLO_MASK_8BITMIME) == 0) + session->features |= SMTP_FEATURE_8BITMIME; + } else if (strcasecmp(word, "PIPELINING") == 0) { + if ((discard_mask & EHLO_MASK_PIPELINING) == 0) + session->features |= SMTP_FEATURE_PIPELINING; + } else if (strcasecmp(word, "XFORWARD") == 0) { + if ((discard_mask & EHLO_MASK_XFORWARD) == 0) + while ((word = mystrtok(&words, " \t")) != 0) + session->features |= + name_code(xforward_features, + NAME_CODE_FLAG_NONE, word); + } else if (strcasecmp(word, "SIZE") == 0) { + if ((discard_mask & EHLO_MASK_SIZE) == 0) { + session->features |= SMTP_FEATURE_SIZE; + if ((word = mystrtok(&words, " \t")) != 0) { + if (!alldig(word)) + msg_warn("bad EHLO SIZE limit \"%s\" from %s", + word, session->namaddrport); + else + session->size_limit = off_cvt_string(word); + } } - } #ifdef USE_TLS - } else if (strcasecmp(word, "STARTTLS") == 0) { - /* Ignored later if we already sent STARTTLS. */ - if ((discard_mask & EHLO_MASK_STARTTLS) == 0) - session->features |= SMTP_FEATURE_STARTTLS; + } else if (strcasecmp(word, "STARTTLS") == 0) { + /* Ignored later if we already sent STARTTLS. */ + if ((discard_mask & EHLO_MASK_STARTTLS) == 0) + session->features |= SMTP_FEATURE_STARTTLS; #endif #ifdef USE_SASL_AUTH - } else if (var_smtp_sasl_enable && strcasecmp(word, "AUTH") == 0) { - if ((discard_mask & EHLO_MASK_AUTH) == 0) - smtp_sasl_helo_auth(session, words); + } else if (var_smtp_sasl_enable + && strcasecmp(word, "AUTH") == 0) { + if ((discard_mask & EHLO_MASK_AUTH) == 0) + smtp_sasl_helo_auth(session, words); #endif - } else if (strcasecmp(word, "DSN") == 0) { - if ((discard_mask & EHLO_MASK_DSN) == 0) - session->features |= SMTP_FEATURE_DSN; + } else if (strcasecmp(word, "DSN") == 0) { + if ((discard_mask & EHLO_MASK_DSN) == 0) + session->features |= SMTP_FEATURE_DSN; + } + n++; } - n++; } } if (msg_verbose) @@ -600,16 +612,6 @@ int smtp_helo(SMTP_STATE *state) #ifdef USE_SASL_AUTH if (var_smtp_sasl_enable && (session->features & SMTP_FEATURE_AUTH)) return (smtp_sasl_helo_login(state)); - else if (var_smtp_sasl_enable - && *var_smtp_sasl_passwd - && !var_smtp_sender_auth - && var_smtp_sasl_enforce - && smtp_sasl_passwd_lookup(session) != 0) - return (smtp_site_fail(state, DSN_BY_LOCAL_MTA, - SMTP_RESP_FAKE(&fake, "4.7.0"), - "SASL login/password exists, but host %s " - "does not announce SASL authentication support", - session->namaddr)); #endif return (0); @@ -744,11 +746,22 @@ static int smtp_start_tls(SMTP_STATE *state) DONT_USE_DEAD_SESSION; /* - * If TLS is optional, try again, this time without TLS. - * Specifically, this session is not final, don't defer any - * recipients yet. + * If TLS is optional, try delivery to the same server over a + * plaintext connection. Otherwise we would defer mail forever with + * destinations that have no alternate MX host. + * + * Don't fall back to plaintext if we were willing to use SASL-over-TLS + * authentication. If the server doesn't announce SASL support over + * plaintext connections, then we don't want delivery to fail with + * "relay access denied". */ - if (session->tls_level == TLS_LEV_MAY) + if (session->tls_level == TLS_LEV_MAY +#ifdef USE_SASL_AUTH + && !(var_smtp_sasl_enable + && *var_smtp_sasl_passwd + && smtp_sasl_passwd_lookup(session)) +#endif + ) RETRY_AS_PLAINTEXT; return (smtp_site_fail(state, DSN_BY_LOCAL_MTA, SMTP_RESP_FAKE(&fake, "4.7.5"), diff --git a/postfix/src/smtp/smtp_sasl_glue.c b/postfix/src/smtp/smtp_sasl_glue.c index 433258dc7..139f6fd53 100644 --- a/postfix/src/smtp/smtp_sasl_glue.c +++ b/postfix/src/smtp/smtp_sasl_glue.c @@ -175,9 +175,13 @@ int smtp_sasl_passwd_lookup(SMTP_SESSION *session) && (value = mail_addr_find(smtp_sasl_passwd_map, state->request->sender, (char **) 0)) != 0) || (value = maps_find(smtp_sasl_passwd_map, session->host, 0)) != 0 - || (value = maps_find(smtp_sasl_passwd_map, session->dest, 0)) != 0) { + || (value = maps_find(smtp_sasl_passwd_map, session->dest, 0)) != 0) { + if (session->sasl_username) + myfree(session->sasl_username); session->sasl_username = mystrdup(value); passwd = split_at(session->sasl_username, ':'); + if (session->sasl_passwd) + myfree(session->sasl_passwd); session->sasl_passwd = mystrdup(passwd ? passwd : ""); if (msg_verbose) msg_info("%s: host `%s' user `%s' pass `%s'", diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 8425f1d3b..1f6dfdfd8 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -108,6 +108,12 @@ /* .IP "\fBsmtpd_delay_open_until_valid_rcpt (yes)\fR" /* Postpone the start of an SMTP mail transaction until a valid /* RCPT TO command is received. +/* .PP +/* Available in Postfix version 2.3 and later: +/* .IP "\fBsmtpd_tls_always_issue_session_ids (yes)\fR" +/* Force the Postfix SMTP server to issue a TLS session id, even +/* when TLS session caching is turned off (smtpd_tls_session_cache_database +/* is empty). /* ADDRESS REWRITING CONTROLS /* .ad /* .fi @@ -278,6 +284,10 @@ /* .IP "\fBsmtpd_tls_CAfile (empty)\fR" /* The file with the certificate of the certification authority /* (CA) that issued the Postfix SMTP server certificate. +/* .IP "\fBsmtpd_tls_always_issue_session_ids (yes)\fR" +/* Force the Postfix SMTP server to issue a TLS session id, even +/* when TLS session caching is turned off (smtpd_tls_session_cache_database +/* is empty). /* .IP "\fBsmtpd_tls_ask_ccert (no)\fR" /* Ask a remote SMTP client for a client certificate. /* .IP "\fBsmtpd_tls_auth_only (no)\fR" @@ -520,7 +530,7 @@ /* .PP /* Available in Postfix version 2.3 and later: /* .IP "\fBsmtpd_peername_lookup (yes)\fR" -/* Attempt to look up the Postfix SMTP client hostname, and verify that +/* Attempt to look up the remote SMTP client hostname, and verify that /* the name matches the client IP address. /* .PP /* The per SMTP client connection count and request rate limits are @@ -1070,6 +1080,7 @@ char *var_smtpd_tls_mand_proto; bool var_smtpd_tls_received_header; bool var_smtpd_tls_req_ccert; int var_smtpd_tls_scache_timeout; +bool var_smtpd_tls_set_sessid; int var_tls_daemon_rand_bytes; #endif @@ -1520,7 +1531,7 @@ static void helo_reset(SMTPD_STATE *state) if (state->helo_name) { myfree(state->helo_name); state->helo_name = 0; - if (smtpd_milters) + if (SMTPD_STAND_ALONE(state) == 0 && smtpd_milters != 0) milter_abort(smtpd_milters); } } @@ -4218,6 +4229,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv) props.verifydepth = var_smtpd_tls_ccert_vd; props.cache_type = TLS_MGR_SCACHE_SMTPD; props.scache_timeout = var_smtpd_tls_scache_timeout; + props.set_sessid = var_smtpd_tls_set_sessid; props.cert_file = var_smtpd_tls_cert_file; props.key_file = var_smtpd_tls_key_file; props.dcert_file = var_smtpd_tls_dcert_file; @@ -4250,14 +4262,14 @@ static void pre_jail_init(char *unused_name, char **unused_argv) msg_warn("Can't require client certs unless TLS is required"); props.cipherlist = - tls_cipher_list(enforce_tls ? - tls_cipher_level(var_smtpd_tls_mand_ciph) : - TLS_CIPHER_EXPORT, + tls_cipher_list(enforce_tls ? + tls_cipher_level(var_smtpd_tls_mand_ciph) : + TLS_CIPHER_EXPORT, var_smtpd_tls_excl_ciph, havecert ? "" : "aRSA aDSS", wantcert ? "aNULL" : "", - enforce_tls ? var_smtpd_tls_mand_excl : - TLS_END_EXCLUDE, + enforce_tls ? var_smtpd_tls_mand_excl : + TLS_END_EXCLUDE, TLS_END_EXCLUDE); if (props.cipherlist == 0) { @@ -4268,8 +4280,8 @@ static void pre_jail_init(char *unused_name, char **unused_argv) var_smtpd_tls_excl_ciph, havecert ? "" : "aRSA aDSS", wantcert ? "aNULL" : "", - enforce_tls ? var_smtpd_tls_mand_excl : - TLS_END_EXCLUDE, + enforce_tls ? var_smtpd_tls_mand_excl : + TLS_END_EXCLUDE, TLS_END_EXCLUDE); } if (havecert || oknocert) @@ -4439,6 +4451,7 @@ int main(int argc, char **argv) VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert, VAR_SMTPD_TLS_RCERT, DEF_SMTPD_TLS_RCERT, &var_smtpd_tls_req_ccert, VAR_SMTPD_TLS_RECHEAD, DEF_SMTPD_TLS_RECHEAD, &var_smtpd_tls_received_header, + VAR_SMTPD_TLS_SET_SESSID, DEF_SMTPD_TLS_SET_SESSID, &var_smtpd_tls_set_sessid, #endif VAR_SMTPD_PEERNAME_LOOKUP, DEF_SMTPD_PEERNAME_LOOKUP, &var_smtpd_peername_lookup, VAR_SMTPD_DELAY_OPEN, DEF_SMTPD_DELAY_OPEN, &var_smtpd_delay_open, diff --git a/postfix/src/tls/tls.h b/postfix/src/tls/tls.h index 8bee86f5d..f13702327 100644 --- a/postfix/src/tls/tls.h +++ b/postfix/src/tls/tls.h @@ -17,7 +17,7 @@ #include