Prereq: "2.11.8" diff -cr --new-file /var/tmp/postfix-2.11.8/src/global/mail_version.h ./src/global/mail_version.h *** /var/tmp/postfix-2.11.8/src/global/mail_version.h 2016-05-15 12:57:28.000000000 -0400 --- ./src/global/mail_version.h 2016-12-31 19:49:42.000000000 -0500 *************** *** 20,27 **** * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ ! #define MAIL_RELEASE_DATE "20150515" ! #define MAIL_VERSION_NUMBER "2.11.8" #ifdef SNAPSHOT #define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE --- 20,27 ---- * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ ! #define MAIL_RELEASE_DATE "20170101" ! #define MAIL_VERSION_NUMBER "2.11.9" #ifdef SNAPSHOT #define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff -cr --new-file /var/tmp/postfix-2.11.8/HISTORY ./HISTORY *** /var/tmp/postfix-2.11.8/HISTORY 2016-05-15 13:09:59.000000000 -0400 --- ./HISTORY 2016-12-31 19:40:34.000000000 -0500 *************** *** 19750,19752 **** --- 19750,19782 ---- 20160515 Portability: OpenBSD 6.0. Files: makedefs, util/sys_defs.h. + + 20160717 + + Bugfix (introduced: Postfix 1.1): the virtual(8) delivery + agent discarded the error result from vstream_fseek(). + File: virtual/mailbox.c. + + 20160730 + + Bugfix (introduced: 20090614): with concurrent connections + from the same client IP address, and after-220 tests enabled, + postscreen could overwrite the cached "all tests completed" + result of one connection that completed the after-220 tests, + with the "some tests not completed" result of a concurrent + connection where the client hung up later, without completing + the after-220 tests. + + 20161105 + + Bugfix (introduced: Postfix 1.1): the postsuper command did + not count a successful rename operation after error recovery. + Problem reported by Markus Schönhaber. File: postsuper/postsuper.c. + + 20161220 + + Bugfix (introduced: Postfix 2.1.0): the Postfix SMTP daemon + did not query sender_canonical_maps when rejecting unknown + senders with "smtpd_reject_unlisted_recipient = yes" or + with reject_unlisted_sender. Stephen R. van den Berg (Mr. + procmail). Files: smtpd/smtpd.c, smtpd/smtpd_check.c. diff -cr --new-file /var/tmp/postfix-2.11.8/src/cleanup/cleanup_milter.c ./src/cleanup/cleanup_milter.c *** /var/tmp/postfix-2.11.8/src/cleanup/cleanup_milter.c 2016-04-10 18:14:21.000000000 -0400 --- ./src/cleanup/cleanup_milter.c 2016-05-15 15:02:13.000000000 -0400 *************** *** 2528,2535 **** maps_free(cleanup_send_bcc_maps); cleanup_send_bcc_maps = maps_create("sender_bcc_maps", argv->argv[1], ! DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX ! | DICT_FLAG_UTF8_REQUEST); state->flags |= CLEANUP_FLAG_BCC_OK; var_rcpt_delim = ""; } --- 2528,2534 ---- maps_free(cleanup_send_bcc_maps); cleanup_send_bcc_maps = maps_create("sender_bcc_maps", argv->argv[1], ! DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); state->flags |= CLEANUP_FLAG_BCC_OK; var_rcpt_delim = ""; } diff -cr --new-file /var/tmp/postfix-2.11.8/src/postscreen/postscreen.c ./src/postscreen/postscreen.c *** /var/tmp/postfix-2.11.8/src/postscreen/postscreen.c 2016-04-11 08:51:26.000000000 -0400 --- ./src/postscreen/postscreen.c 2016-12-31 19:21:07.000000000 -0500 *************** *** 754,759 **** --- 754,760 ---- * valid. */ if ((state->flags & PSC_STATE_MASK_ANY_FAIL) == 0 + && state->client_info->concurrency == 1 && psc_cache_map != 0 && (stamp_str = psc_cache_lookup(psc_cache_map, state->smtp_client_addr)) != 0) { saved_flags = state->flags; *************** *** 767,772 **** --- 768,780 ---- psc_conclude(state); return; } + } else if (state->client_info->concurrency > 1) { + saved_flags = state->flags; + psc_todo_tests(state, event_time()); + state->flags |= saved_flags; + if (msg_verbose) + msg_info("%s: new + recent flags: %s", + myname, psc_print_state_flags(state->flags, myname)); } else { saved_flags = state->flags; psc_new_tests(state); *************** *** 818,823 **** --- 826,832 ---- char *unused_context) { PSC_STATE dummy; + PSC_CLIENT_INFO dummy_client_info; /* * This function is called by the cache cleanup pseudo thread. *************** *** 827,832 **** --- 836,842 ---- * silly logging we remove the cache entry only after all tests have * expired longer ago than the cache retention time. */ + dummy.client_info = &dummy_client_info; psc_parse_tests(&dummy, stamp_str, event_time() - var_psc_cache_ret); return ((dummy.flags & PSC_STATE_MASK_ANY_TODO) == 0); } diff -cr --new-file /var/tmp/postfix-2.11.8/src/postscreen/postscreen.h ./src/postscreen/postscreen.h *** /var/tmp/postfix-2.11.8/src/postscreen/postscreen.h 2013-05-13 16:58:21.000000000 -0400 --- ./src/postscreen/postscreen.h 2016-12-31 19:21:07.000000000 -0500 *************** *** 55,60 **** --- 55,69 ---- #define PSC_TINDX_BYTNAME(tname) (PSC_TINDX_ ## tname) /* + * Per-client shared state. + */ + typedef struct { + int concurrency; /* per-client */ + int pass_new_count; /* per-client */ + time_t expire_time[PSC_TINDX_COUNT]; /* per-test expiration */ + } PSC_CLIENT_INFO; + + /* * Per-session state. */ typedef struct { *************** *** 66,78 **** char *smtp_client_port; /* client port */ char *smtp_server_addr; /* server address */ char *smtp_server_port; /* server port */ - int client_concurrency; /* per-client */ const char *final_reply; /* cause for hanging up */ VSTRING *send_buf; /* pending output */ /* Test context. */ struct timeval start_time; /* start of current test */ const char *test_name; /* name of current test */ ! time_t expire_time[PSC_TINDX_COUNT]; /* per-test expiration */ VSTRING *dnsbl_reply; /* dnsbl reject text */ int dnsbl_score; /* saved DNSBL score */ const char *dnsbl_name; /* DNSBL name with largest weight */ --- 75,86 ---- char *smtp_client_port; /* client port */ char *smtp_server_addr; /* server address */ char *smtp_server_port; /* server port */ const char *final_reply; /* cause for hanging up */ VSTRING *send_buf; /* pending output */ /* Test context. */ struct timeval start_time; /* start of current test */ const char *test_name; /* name of current test */ ! PSC_CLIENT_INFO *client_info; /* shared client state */ VSTRING *dnsbl_reply; /* dnsbl reject text */ int dnsbl_score; /* saved DNSBL score */ const char *dnsbl_name; /* DNSBL name with largest weight */ *************** *** 94,104 **** * Emulate legacy ad-hoc variables on top of indexable time stamps. This * avoids massive scar tissue during initial feature development. */ ! #define pregr_stamp expire_time[PSC_TINDX_PREGR] ! #define dnsbl_stamp expire_time[PSC_TINDX_DNSBL] ! #define pipel_stamp expire_time[PSC_TINDX_PIPEL] ! #define nsmtp_stamp expire_time[PSC_TINDX_NSMTP] ! #define barlf_stamp expire_time[PSC_TINDX_BARLF] /* * Special expiration time values. --- 102,115 ---- * Emulate legacy ad-hoc variables on top of indexable time stamps. This * avoids massive scar tissue during initial feature development. */ ! #define pregr_stamp client_info->expire_time[PSC_TINDX_PREGR] ! #define dnsbl_stamp client_info->expire_time[PSC_TINDX_DNSBL] ! #define pipel_stamp client_info->expire_time[PSC_TINDX_PIPEL] ! #define nsmtp_stamp client_info->expire_time[PSC_TINDX_NSMTP] ! #define barlf_stamp client_info->expire_time[PSC_TINDX_BARLF] ! ! /* Minize the patch size for stable releases. */ ! #define client_concurrency client_info->concurrency /* * Special expiration time values. *************** *** 489,505 **** #define PSC_INIT_TESTS(dst) do { \ time_t *_it_stamp_p; \ (dst)->flags = 0; \ ! for (_it_stamp_p = (dst)->expire_time; \ ! _it_stamp_p < (dst)->expire_time + PSC_TINDX_COUNT; \ _it_stamp_p++) \ *_it_stamp_p = PSC_TIME_STAMP_INVALID; \ } while (0) #define PSC_BEGIN_TESTS(state, name) do { \ (state)->test_name = (name); \ GETTIMEOFDAY(&(state)->start_time); \ } while (0) extern void psc_new_tests(PSC_STATE *); extern void psc_parse_tests(PSC_STATE *, const char *, time_t); extern char *psc_print_tests(VSTRING *, PSC_STATE *); extern char *psc_print_grey_key(VSTRING *, const char *, const char *, const char *, const char *); --- 500,520 ---- #define PSC_INIT_TESTS(dst) do { \ time_t *_it_stamp_p; \ (dst)->flags = 0; \ ! for (_it_stamp_p = (dst)->client_info->expire_time; \ ! _it_stamp_p < (dst)->client_info->expire_time + PSC_TINDX_COUNT; \ _it_stamp_p++) \ *_it_stamp_p = PSC_TIME_STAMP_INVALID; \ } while (0) + #define PSC_INIT_TEST_FLAGS_ONLY(dst) do { \ + (dst)->flags = 0; \ + } while (0) #define PSC_BEGIN_TESTS(state, name) do { \ (state)->test_name = (name); \ GETTIMEOFDAY(&(state)->start_time); \ } while (0) extern void psc_new_tests(PSC_STATE *); extern void psc_parse_tests(PSC_STATE *, const char *, time_t); + extern void psc_todo_tests(PSC_STATE *, time_t); extern char *psc_print_tests(VSTRING *, PSC_STATE *); extern char *psc_print_grey_key(VSTRING *, const char *, const char *, const char *, const char *); diff -cr --new-file /var/tmp/postfix-2.11.8/src/postscreen/postscreen_early.c ./src/postscreen/postscreen_early.c *** /var/tmp/postfix-2.11.8/src/postscreen/postscreen_early.c 2013-10-13 16:09:54.000000000 -0400 --- ./src/postscreen/postscreen_early.c 2016-12-31 19:21:07.000000000 -0500 *************** *** 87,94 **** state->flags |= PSC_STATE_FLAG_BYTINDX_PASS(tindx); } /* Update expiration even if the test was completed or disabled. */ ! if (state->expire_time[tindx] < now + var_psc_dnsbl_ttl) ! state->expire_time[tindx] = now + var_psc_dnsbl_ttl; } } } --- 87,94 ---- state->flags |= PSC_STATE_FLAG_BYTINDX_PASS(tindx); } /* Update expiration even if the test was completed or disabled. */ ! if (state->client_info->expire_time[tindx] < now + var_psc_dnsbl_ttl) ! state->client_info->expire_time[tindx] = now + var_psc_dnsbl_ttl; } } } diff -cr --new-file /var/tmp/postfix-2.11.8/src/postscreen/postscreen_misc.c ./src/postscreen/postscreen_misc.c *** /var/tmp/postfix-2.11.8/src/postscreen/postscreen_misc.c 2011-01-02 11:20:40.000000000 -0500 --- ./src/postscreen/postscreen_misc.c 2016-12-31 19:21:07.000000000 -0500 *************** *** 105,117 **** if ((state->flags & PSC_STATE_MASK_ANY_PASS) != 0 && (state->flags & PSC_STATE_MASK_ANY_PASS) == PSC_STATE_FLAGS_TODO_TO_PASS(state->flags & PSC_STATE_MASK_ANY_TODO)) ! msg_info("PASS %s [%s]:%s", (state->flags & PSC_STATE_FLAG_NEW) == 0 ? "OLD" : "NEW", PSC_CLIENT_ADDR_PORT(state)); /* * Update the postscreen cache. This still supports a scenario where a * client gets whitelisted in the course of multiple sessions, as long as ! * that client does not "fail" any test. */ if ((state->flags & PSC_STATE_MASK_ANY_UPDATE) != 0 && psc_cache_map != 0) { --- 105,121 ---- if ((state->flags & PSC_STATE_MASK_ANY_PASS) != 0 && (state->flags & PSC_STATE_MASK_ANY_PASS) == PSC_STATE_FLAGS_TODO_TO_PASS(state->flags & PSC_STATE_MASK_ANY_TODO)) ! msg_info("PASS %s [%s]:%s", (state->flags & PSC_STATE_FLAG_NEW) == 0 ! || state->client_info->pass_new_count++ > 0 ? "OLD" : "NEW", PSC_CLIENT_ADDR_PORT(state)); /* * Update the postscreen cache. This still supports a scenario where a * client gets whitelisted in the course of multiple sessions, as long as ! * that client does not "fail" any test. Don't try to optimize away cache ! * updates; we want cached information to be up-to-date even if a test ! * result is renewed during overlapping SMTP sessions, and even if ! * 'postfix reload' happens in the middle of that. */ if ((state->flags & PSC_STATE_MASK_ANY_UPDATE) != 0 && psc_cache_map != 0) { diff -cr --new-file /var/tmp/postfix-2.11.8/src/postscreen/postscreen_state.c ./src/postscreen/postscreen_state.c *** /var/tmp/postfix-2.11.8/src/postscreen/postscreen_state.c 2013-05-10 21:17:34.000000000 -0400 --- ./src/postscreen/postscreen_state.c 2016-12-31 19:21:07.000000000 -0500 *************** *** 61,67 **** /* psc_new_session_state() creates a new session state object /* for the specified client stream, and increments the /* psc_check_queue_length counter. The flags and per-test time ! /* stamps are initialized with PSC_INIT_TESTS(). The addr and /* port arguments are null-terminated strings with the remote /* SMTP client endpoint. The _reply members are set to /* polite "try again" SMTP replies. The protocol member is set --- 61,68 ---- /* psc_new_session_state() creates a new session state object /* for the specified client stream, and increments the /* psc_check_queue_length counter. The flags and per-test time ! /* stamps are initialized with PSC_INIT_TESTS(), or for concurrent ! /* sessions, with PSC_INIT_TEST_FLAGS_ONLY(). The addr and /* port arguments are null-terminated strings with the remote /* SMTP client endpoint. The _reply members are set to /* polite "try again" SMTP replies. The protocol member is set *************** *** 149,158 **** const char *server_port) { PSC_STATE *state; - HTABLE_INFO *ht; state = (PSC_STATE *) mymalloc(sizeof(*state)); - PSC_INIT_TESTS(state); if ((state->smtp_client_stream = stream) != 0) psc_check_queue_length++; state->smtp_server_fd = (-1); --- 150,157 ---- *************** *** 188,197 **** /* * Update the per-client session count. */ ! if ((ht = htable_locate(psc_client_concurrency, client_addr)) == 0) ! ht = htable_enter(psc_client_concurrency, client_addr, (char *) 0); ! ht->value += 1; ! state->client_concurrency = CAST_CHAR_PTR_TO_INT(ht->value); return (state); } --- 187,205 ---- /* * Update the per-client session count. */ ! if ((state->client_info = (PSC_CLIENT_INFO *) ! htable_find(psc_client_concurrency, client_addr)) == 0) { ! state->client_info = (PSC_CLIENT_INFO *) ! mymalloc(sizeof(state->client_info[0])); ! (void) htable_enter(psc_client_concurrency, client_addr, ! (void *) state->client_info); ! PSC_INIT_TESTS(state); ! state->client_info->concurrency = 1; ! state->client_info->pass_new_count = 0; ! } else { ! PSC_INIT_TEST_FLAGS_ONLY(state); ! state->client_info->concurrency += 1; ! } return (state); } *************** *** 210,218 **** state->smtp_client_addr)) == 0) msg_panic("%s: unknown client address: %s", myname, state->smtp_client_addr); ! if (--(ht->value) == 0) ! htable_delete(psc_client_concurrency, state->smtp_client_addr, ! (void (*) (char *)) 0); if (state->smtp_client_stream != 0) { event_server_disconnect(state->smtp_client_stream); --- 218,225 ---- state->smtp_client_addr)) == 0) msg_panic("%s: unknown client address: %s", myname, state->smtp_client_addr); ! if (--(state->client_info->concurrency) == 0) ! htable_delete(psc_client_concurrency, state->smtp_client_addr, myfree); if (state->smtp_client_stream != 0) { event_server_disconnect(state->smtp_client_stream); diff -cr --new-file /var/tmp/postfix-2.11.8/src/postscreen/postscreen_tests.c ./src/postscreen/postscreen_tests.c *** /var/tmp/postfix-2.11.8/src/postscreen/postscreen_tests.c 2013-05-12 13:09:08.000000000 -0400 --- ./src/postscreen/postscreen_tests.c 2016-12-31 19:21:07.000000000 -0500 *************** *** 17,22 **** --- 17,27 ---- /* const char *stamp_text; /* time_t time_value; /* + /* void psc_todo_tests(state, time_value) + /* PSC_STATE *state; + /* const char *stamp_text; + /* time_t time_value; + /* /* char *psc_print_tests(buffer, state) /* VSTRING *buffer; /* PSC_STATE *state; *************** *** 41,53 **** /* zeroes all the flags bits. These values are not meant to /* be stored into the postscreen(8) cache. /* /* psc_new_tests() sets all test expiration time stamps to ! /* PSC_TIME_STAMP_NEW, and overwrites all flags bits. Only ! /* enabled tests are flagged with PSC_STATE_FLAG_TODO; the ! /* object is flagged with PSC_STATE_FLAG_NEW. /* ! /* psc_parse_tests() parses a cache file record and overwrites ! /* all flags bits. Tests are considered "expired" when they /* would be expired at the specified time value. Only enabled /* tests are flagged as "expired"; the object is flagged as /* "new" if some enabled tests have "new" time stamps. --- 46,63 ---- /* zeroes all the flags bits. These values are not meant to /* be stored into the postscreen(8) cache. /* + /* PSC_INIT_TEST_FLAGS_ONLY() zeroes all the flag bits. It + /* should be used when the time stamps are already initialized. + /* /* psc_new_tests() sets all test expiration time stamps to ! /* PSC_TIME_STAMP_NEW, and invokes psc_todo_tests(). ! /* ! /* psc_parse_tests() parses a cache file record and invokes ! /* psc_todo_tests(). /* ! /* psc_todo_tests() overwrites all per-session flag bits, and ! /* populates the flags based on test expiration time stamp ! /* information. Tests are considered "expired" when they /* would be expired at the specified time value. Only enabled /* tests are flagged as "expired"; the object is flagged as /* "new" if some enabled tests have "new" time stamps. *************** *** 125,135 **** { /* - * We know this client is brand new. - */ - state->flags = PSC_STATE_FLAG_NEW; - - /* * Give all tests a PSC_TIME_STAMP_NEW time stamp, so that we can later * recognize cache entries that haven't passed all enabled tests. When we * write a cache entry to the database, any new-but-disabled tests will --- 135,140 ---- *************** *** 142,160 **** state->barlf_stamp = PSC_TIME_STAMP_NEW; /* ! * Don't flag disabled tests as "todo", because there would be no way to ! * make those bits go away. */ ! if (PSC_PREGR_TEST_ENABLE()) ! state->flags |= PSC_STATE_FLAG_PREGR_TODO; ! if (PSC_DNSBL_TEST_ENABLE()) ! state->flags |= PSC_STATE_FLAG_DNSBL_TODO; ! if (var_psc_pipel_enable) ! state->flags |= PSC_STATE_FLAG_PIPEL_TODO; ! if (var_psc_nsmtp_enable) ! state->flags |= PSC_STATE_FLAG_NSMTP_TODO; ! if (var_psc_barlf_enable) ! state->flags |= PSC_STATE_FLAG_BARLF_TODO; } /* psc_parse_tests - parse test results from cache */ --- 147,155 ---- state->barlf_stamp = PSC_TIME_STAMP_NEW; /* ! * Determine what tests need to be completed. */ ! psc_todo_tests(state, PSC_TIME_STAMP_NEW + 1); } /* psc_parse_tests - parse test results from cache */ *************** *** 165,193 **** { const char *start = stamp_str; char *cp; ! time_t *time_stamps = state->expire_time; time_t *sp; /* - * We don't know what tests have expired or have never passed. - */ - state->flags = 0; - - /* * Parse the cache entry, and allow for older postscreen versions that * implemented fewer tests. We pretend that the newer tests were disabled * at the time that the cache entry was written. - * - * Flag the cache entry as "new" when the cache entry has fields for all - * enabled tests, but the remote SMTP client has not yet passed all those - * tests. */ for (sp = time_stamps; sp < time_stamps + PSC_TINDX_COUNT; sp++) { *sp = strtoul(start, &cp, 10); if (*start == 0 || (*cp != '\0' && *cp != ';') || errno == ERANGE) *sp = PSC_TIME_STAMP_DISABLED; - if (*sp == PSC_TIME_STAMP_NEW) - state->flags |= PSC_STATE_FLAG_NEW; if (msg_verbose) msg_info("%s -> %lu", start, (unsigned long) *sp); if (*cp == ';') --- 160,177 ---- { const char *start = stamp_str; char *cp; ! time_t *time_stamps = state->client_info->expire_time; time_t *sp; /* * Parse the cache entry, and allow for older postscreen versions that * implemented fewer tests. We pretend that the newer tests were disabled * at the time that the cache entry was written. */ for (sp = time_stamps; sp < time_stamps + PSC_TINDX_COUNT; sp++) { *sp = strtoul(start, &cp, 10); if (*start == 0 || (*cp != '\0' && *cp != ';') || errno == ERANGE) *sp = PSC_TIME_STAMP_DISABLED; if (msg_verbose) msg_info("%s -> %lu", start, (unsigned long) *sp); if (*cp == ';') *************** *** 197,202 **** --- 181,214 ---- } /* + * Determine what tests need to be completed. + */ + psc_todo_tests(state, time_value); + } + + /* psc_todo_tests - determine what tests to perform */ + + void psc_todo_tests(PSC_STATE *state, time_t time_value) + { + time_t *time_stamps = state->client_info->expire_time; + time_t *sp; + + /* + * Reset all per-session flags. + */ + state->flags = 0; + + /* + * Flag the tests as "new" when the cache entry has fields for all + * enabled tests, but the remote SMTP client has not yet passed all those + * tests. + */ + for (sp = time_stamps; sp < time_stamps + PSC_TINDX_COUNT; sp++) { + if (*sp == PSC_TIME_STAMP_NEW) + state->flags |= PSC_STATE_FLAG_NEW; + } + + /* * Don't flag disabled tests as "todo", because there would be no way to * make those bits go away. */ diff -cr --new-file /var/tmp/postfix-2.11.8/src/postsuper/postsuper.c ./src/postsuper/postsuper.c *** /var/tmp/postfix-2.11.8/src/postsuper/postsuper.c 2012-01-24 19:41:08.000000000 -0500 --- ./src/postsuper/postsuper.c 2016-11-05 10:49:49.000000000 -0400 *************** *** 430,436 **** if ((ret = sane_rename(old, new)) < 0) { if (errno != ENOENT || mail_queue_mkdirs(new) < 0 ! || sane_rename(old, new) < 0) if (errno != ENOENT) msg_fatal("rename file %s as %s: %m", old, new); } else { --- 430,436 ---- if ((ret = sane_rename(old, new)) < 0) { if (errno != ENOENT || mail_queue_mkdirs(new) < 0 ! || (ret = sane_rename(old, new)) < 0) if (errno != ENOENT) msg_fatal("rename file %s as %s: %m", old, new); } else { diff -cr --new-file /var/tmp/postfix-2.11.8/src/smtpd/smtpd.c ./src/smtpd/smtpd.c *** /var/tmp/postfix-2.11.8/src/smtpd/smtpd.c 2015-07-19 19:04:39.000000000 -0400 --- ./src/smtpd/smtpd.c 2016-12-31 19:29:57.000000000 -0500 *************** *** 1172,1177 **** --- 1172,1178 ---- int var_strict_rfc821_env; bool var_disable_vrfy_cmd; char *var_canonical_maps; + char *var_send_canon_maps; char *var_rcpt_canon_maps; char *var_virt_alias_maps; char *var_virt_mailbox_maps; *************** *** 5382,5387 **** --- 5383,5389 ---- VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0, VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes, 0, 0, VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps, 0, 0, + VAR_SEND_CANON_MAPS, DEF_SEND_CANON_MAPS, &var_send_canon_maps, 0, 0, VAR_RCPT_CANON_MAPS, DEF_RCPT_CANON_MAPS, &var_rcpt_canon_maps, 0, 0, VAR_VIRT_ALIAS_MAPS, DEF_VIRT_ALIAS_MAPS, &var_virt_alias_maps, 0, 0, VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0, diff -cr --new-file /var/tmp/postfix-2.11.8/src/smtpd/smtpd_check.c ./src/smtpd/smtpd_check.c *** /var/tmp/postfix-2.11.8/src/smtpd/smtpd_check.c 2014-09-20 20:34:20.000000000 -0400 --- ./src/smtpd/smtpd_check.c 2016-12-31 19:38:41.000000000 -0500 *************** *** 274,279 **** --- 274,280 ---- * trivial-rewrite resolver. */ static MAPS *local_rcpt_maps; + static MAPS *send_canon_maps; static MAPS *rcpt_canon_maps; static MAPS *canonical_maps; static MAPS *virt_alias_maps; *************** *** 610,615 **** --- 611,618 ---- */ local_rcpt_maps = maps_create(VAR_LOCAL_RCPT_MAPS, var_local_rcpt_maps, DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); + send_canon_maps = maps_create(VAR_SEND_CANON_MAPS, var_send_canon_maps, + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); rcpt_canon_maps = maps_create(VAR_RCPT_CANON_MAPS, var_rcpt_canon_maps, DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX); canonical_maps = maps_create(VAR_CANONICAL_MAPS, var_canonical_maps, *************** *** 4716,4722 **** DSN_SPLIT dp; if (msg_verbose) ! msg_info(">>> CHECKING RECIPIENT MAPS <<<"); /* * Resolve the address. --- 4719,4725 ---- DSN_SPLIT dp; if (msg_verbose) ! msg_info(">>> CHECKING %s VALIDATION MAPS <<<", reply_class); /* * Resolve the address. *************** *** 4742,4747 **** --- 4745,4752 ---- * domains. */ if (MATCH(rcpt_canon_maps, CONST_STR(reply->recipient)) + || (strcmp(reply_class, SMTPD_NAME_SENDER) == 0 + && MATCH(send_canon_maps, CONST_STR(reply->recipient))) || MATCH(canonical_maps, CONST_STR(reply->recipient)) || MATCH(virt_alias_maps, CONST_STR(reply->recipient))) return (0); *************** *** 5071,5076 **** --- 5076,5082 ---- char *var_rcpt_delim; char *var_rest_classes; char *var_alias_maps; + char *var_send_canon_maps; char *var_rcpt_canon_maps; char *var_canonical_maps; char *var_virt_alias_maps; *************** *** 5121,5126 **** --- 5127,5133 ---- VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim, VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes, VAR_ALIAS_MAPS, DEF_ALIAS_MAPS, &var_alias_maps, + VAR_SEND_CANON_MAPS, DEF_SEND_CANON_MAPS, &var_send_canon_maps, VAR_RCPT_CANON_MAPS, DEF_RCPT_CANON_MAPS, &var_rcpt_canon_maps, VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps, VAR_VIRT_ALIAS_MAPS, DEF_VIRT_ALIAS_MAPS, &var_virt_alias_maps, *************** *** 5643,5648 **** --- 5650,5671 ---- resp = 0; break; } + if (strcasecmp(args->argv[0], VAR_SEND_CANON_MAPS) == 0) { + UPDATE_STRING(var_send_canon_maps, args->argv[1]); + UPDATE_MAPS(send_canon_maps, VAR_SEND_CANON_MAPS, + var_send_canon_maps, DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX); + resp = 0; + break; + } + if (strcasecmp(args->argv[0], VAR_RCPT_CANON_MAPS) == 0) { + UPDATE_STRING(var_rcpt_canon_maps, args->argv[1]); + UPDATE_MAPS(rcpt_canon_maps, VAR_RCPT_CANON_MAPS, + var_rcpt_canon_maps, DICT_FLAG_LOCK + | DICT_FLAG_FOLD_FIX); + resp = 0; + break; + } if (strcasecmp(args->argv[0], VAR_RBL_REPLY_MAPS) == 0) { UPDATE_STRING(var_rbl_reply_maps, args->argv[1]); UPDATE_MAPS(rbl_reply_maps, VAR_RBL_REPLY_MAPS, diff -cr --new-file /var/tmp/postfix-2.11.8/src/virtual/mailbox.c ./src/virtual/mailbox.c *** /var/tmp/postfix-2.11.8/src/virtual/mailbox.c 2011-12-23 21:13:32.000000000 -0500 --- ./src/virtual/mailbox.c 2016-08-22 17:24:31.000000000 -0400 *************** *** 80,86 **** int mail_copy_status; int deliver_status; int copy_flags; - long end; struct stat st; /* --- 80,85 ---- *************** *** 132,138 **** msg_warn("specify \"%s = no\" to ignore mailbox ownership mismatch", VAR_STRICT_MBOX_OWNER); } else { ! end = vstream_fseek(mp->fp, (off_t) 0, SEEK_END); mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), mp->fp, copy_flags, "\n", why); } --- 131,139 ---- msg_warn("specify \"%s = no\" to ignore mailbox ownership mismatch", VAR_STRICT_MBOX_OWNER); } else { ! if (vstream_fseek(mp->fp, (off_t) 0, SEEK_END) < 0) ! msg_fatal("%s: seek queue file %s: %m", ! myname, VSTREAM_PATH(mp->fp)); mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr), mp->fp, copy_flags, "\n", why); }