Prereq: "3.1.3" diff -cr --new-file /var/tmp/postfix-3.1.3/src/global/mail_version.h ./src/global/mail_version.h *** /var/tmp/postfix-3.1.3/src/global/mail_version.h 2016-10-01 19:26:18.000000000 -0400 --- ./src/global/mail_version.h 2017-01-01 13:01:36.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 "20161001" ! #define MAIL_VERSION_NUMBER "3.1.3" #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 "3.1.4" #ifdef SNAPSHOT #define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff -cr --new-file /var/tmp/postfix-3.1.3/HISTORY ./HISTORY *** /var/tmp/postfix-3.1.3/HISTORY 2016-10-01 19:36:45.000000000 -0400 --- ./HISTORY 2017-01-01 12:49:40.000000000 -0500 *************** *** 22217,22222 **** --- 22217,22248 ---- Portability: OpenBSD 6.0. Files: makedefs, util/sys_defs.h. + 20160619 + + Bugfix (introduced: 20091121): with the introduction of + sender_dependent_default_transport_maps, the SMTP daemon + was not updated. This resulted in false rejects with + sender-dependent "error" transports. Based on a fix by + Russell Yanofsky. Files: global/resolve_clnt.c, + global/resolve_clnt.h, smtpd/smtpd_check.c, smtpd/smtpd_check.h, + smtpd/smtpd_milter.c, smtpd/smtpd_resolve.c, smtpd/smtpd_resolve.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. + 20160819 Bugfix (introduced: Postfix 3.0): the makedefs script ignored *************** *** 22258,22260 **** --- 22284,22319 ---- UTF8-encoded text, specify "option_group = client" in Postfix MySQL configuration files. This will be the default setting with Postfix 3.2 and later. + + 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. + + 20161204 + + Bugfix (introduced: Postfix 3.1): cut-and-paste error in + the "postfix tls deploy-server-cert" command, causing the + wrong certfile and keyfile to be used. Viktor Dukhovni. + File: conf/postfix-tls-script. + + Robustness: create a new keyfile when "postfix tls + new-server-cert" is invoked and main.cf specifies a + non-existent keyfile. Viktor Dukhovni. File: + conf/postfix-tls-script. + + 20161206 + + Bugfix (introduced: Postfix 3.0): when receiving a MAIL + FROM...SMTPUTF8 command while smtpd_delay_reject=no, enable + SMTPUTF8 support before processing smtpd_sender_restrictions. + Problem reported by Viktor Dukhovni. File: smtpd/smtpd.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-3.1.3/conf/postfix-tls-script ./conf/postfix-tls-script *** /var/tmp/postfix-3.1.3/conf/postfix-tls-script 2016-02-28 08:09:51.000000000 -0500 --- ./conf/postfix-tls-script 2016-12-04 15:52:29.000000000 -0500 *************** *** 1011,1016 **** --- 1011,1021 ---- # Existing keyfile or empty set_keyfile "${algo}" + if [ -n "${keyfile}" -a ! -f "${keyfile}" ]; then + echo "Key file: ${keyfile} not found, creating new keys" | $WARN + keyfile= + fi + # Try to re-use (copy) existing key. new_server_cert "${algo}" "${bits}" "${keyfile}" "" "$@" || exit 1 ;; *************** *** 1030,1037 **** *) certfile="${config_directory}/${1}" ;; esac case "${2}" in ! /*) certfile="${2}" ;; ! *) certfile="${config_directory}/${2}" ;; esac deploy_server_cert "${certfile}" "${keyfile}" || exit 1 --- 1035,1042 ---- *) certfile="${config_directory}/${1}" ;; esac case "${2}" in ! /*) keyfile="${2}" ;; ! *) keyfile="${config_directory}/${2}" ;; esac deploy_server_cert "${certfile}" "${keyfile}" || exit 1 diff -cr --new-file /var/tmp/postfix-3.1.3/src/postscreen/postscreen.c ./src/postscreen/postscreen.c *** /var/tmp/postfix-3.1.3/src/postscreen/postscreen.c 2016-04-11 08:51:26.000000000 -0400 --- ./src/postscreen/postscreen.c 2017-01-01 12:25:16.000000000 -0500 *************** *** 774,779 **** --- 774,780 ---- * 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; *************** *** 787,792 **** --- 788,800 ---- 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); *************** *** 838,843 **** --- 846,852 ---- void *unused_context) { PSC_STATE dummy; + PSC_CLIENT_INFO dummy_client_info; /* * This function is called by the cache cleanup pseudo thread. *************** *** 847,852 **** --- 856,862 ---- * 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-3.1.3/src/postscreen/postscreen.h ./src/postscreen/postscreen.h *** /var/tmp/postfix-3.1.3/src/postscreen/postscreen.h 2016-01-23 19:39:28.000000000 -0500 --- ./src/postscreen/postscreen.h 2017-01-01 12:25:16.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 */ int dnsbl_ttl; /* saved DNSBL TTL */ --- 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 */ int dnsbl_ttl; /* saved DNSBL TTL */ *************** *** 95,105 **** * 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. --- 103,116 ---- * 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-3.1.3/src/postscreen/postscreen_early.c ./src/postscreen/postscreen_early.c *** /var/tmp/postfix-3.1.3/src/postscreen/postscreen_early.c 2016-01-23 19:38:38.000000000 -0500 --- ./src/postscreen/postscreen_early.c 2017-01-01 12:25:16.000000000 -0500 *************** *** 92,99 **** state->flags |= PSC_STATE_FLAG_BYTINDX_PASS(tindx); } /* Update expiration even if the test was completed or disabled. */ ! if (state->expire_time[tindx] < now + state->dnsbl_ttl) ! state->expire_time[tindx] = now + state->dnsbl_ttl; } } } --- 92,99 ---- 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 + state->dnsbl_ttl) ! state->client_info->expire_time[tindx] = now + state->dnsbl_ttl; } } } diff -cr --new-file /var/tmp/postfix-3.1.3/src/postscreen/postscreen_misc.c ./src/postscreen/postscreen_misc.c *** /var/tmp/postfix-3.1.3/src/postscreen/postscreen_misc.c 2011-01-02 11:20:40.000000000 -0500 --- ./src/postscreen/postscreen_misc.c 2017-01-01 12:25:16.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-3.1.3/src/postscreen/postscreen_state.c ./src/postscreen/postscreen_state.c *** /var/tmp/postfix-3.1.3/src/postscreen/postscreen_state.c 2014-12-06 20:35:33.000000000 -0500 --- ./src/postscreen/postscreen_state.c 2017-01-01 12:25:16.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, (void *) 0); ! ht->value += 1; ! state->client_concurrency = CAST_ANY_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 (*) (void *)) 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-3.1.3/src/postscreen/postscreen_tests.c ./src/postscreen/postscreen_tests.c *** /var/tmp/postfix-3.1.3/src/postscreen/postscreen_tests.c 2013-05-12 13:09:08.000000000 -0400 --- ./src/postscreen/postscreen_tests.c 2017-01-01 12:25:16.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-3.1.3/src/postsuper/postsuper.c ./src/postsuper/postsuper.c *** /var/tmp/postfix-3.1.3/src/postsuper/postsuper.c 2016-02-13 20:27:14.000000000 -0500 --- ./src/postsuper/postsuper.c 2016-11-05 10:48:09.000000000 -0400 *************** *** 435,441 **** 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 { --- 435,441 ---- 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-3.1.3/src/smtpd/Makefile.in ./src/smtpd/Makefile.in *** /var/tmp/postfix-3.1.3/src/smtpd/Makefile.in 2015-07-12 13:20:44.000000000 -0400 --- ./src/smtpd/Makefile.in 2017-01-01 12:22:53.000000000 -0500 *************** *** 531,536 **** --- 531,537 ---- smtpd_resolve.o: ../../include/nvtable.h smtpd_resolve.o: ../../include/resolve_clnt.h smtpd_resolve.o: ../../include/rewrite_clnt.h + smtpd_resolve.o: ../../include/split_at.h smtpd_resolve.o: ../../include/stringops.h smtpd_resolve.o: ../../include/sys_defs.h smtpd_resolve.o: ../../include/vbuf.h diff -cr --new-file /var/tmp/postfix-3.1.3/src/smtpd/smtpd.c ./src/smtpd/smtpd.c *** /var/tmp/postfix-3.1.3/src/smtpd/smtpd.c 2016-09-11 09:43:12.000000000 -0400 --- ./src/smtpd/smtpd.c 2017-01-01 12:48:24.000000000 -0500 *************** *** 1239,1244 **** --- 1239,1245 ---- 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; *************** *** 2280,2286 **** if ((STR(state->addr_buf)[0] == 0 && !allow_empty_addr) || (strict_rfc821 && STR(state->addr_buf)[0] == '@') || (SMTPD_STAND_ALONE(state) == 0 ! && smtpd_check_addr(STR(state->addr_buf), smtputf8) != 0)) { msg_warn("Illegal address syntax from %s in %s command: %s", state->namaddr, state->where, printable(STR(arg->vstrval), '?')); --- 2281,2289 ---- if ((STR(state->addr_buf)[0] == 0 && !allow_empty_addr) || (strict_rfc821 && STR(state->addr_buf)[0] == '@') || (SMTPD_STAND_ALONE(state) == 0 ! && smtpd_check_addr(strcmp(state->where, SMTPD_CMD_MAIL) == 0 ? ! state->recipient : state->sender, ! STR(state->addr_buf), smtputf8) != 0)) { msg_warn("Illegal address syntax from %s in %s command: %s", state->namaddr, state->where, printable(STR(arg->vstrval), '?')); *************** *** 2330,2336 **** char *verp_delims = 0; int rate; int dsn_envid = 0; - int smtputf8 = 0; state->flags &= ~SMTPD_FLAG_SMTPUTF8; state->encoding = 0; --- 2333,2338 ---- *************** *** 2397,2409 **** for (narg = 3; narg < argc; narg++) { arg = argv[narg].strval; if (strcasecmp(arg, "SMTPUTF8") == 0) { /* RFC 6531 */ ! smtputf8 = 1; break; } } } if (extract_addr(state, argv + 2, PERMIT_EMPTY_ADDR, ! var_strict_rfc821_env, smtputf8) != 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "501 5.1.7 Bad sender address syntax"); return (-1); --- 2399,2413 ---- for (narg = 3; narg < argc; narg++) { arg = argv[narg].strval; if (strcasecmp(arg, "SMTPUTF8") == 0) { /* RFC 6531 */ ! /* Fix 20161206: allow UTF8 in smtpd_sender_restrictions. */ ! state->flags |= SMTPD_FLAG_SMTPUTF8; break; } } } if (extract_addr(state, argv + 2, PERMIT_EMPTY_ADDR, ! var_strict_rfc821_env, ! state->flags & SMTPD_FLAG_SMTPUTF8) != 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "501 5.1.7 Bad sender address syntax"); return (-1); *************** *** 2603,2610 **** state->verp_delims = mystrdup(verp_delims); if (dsn_envid) state->dsn_envid = mystrdup(STR(state->dsn_buf)); - if (smtputf8) - state->flags |= SMTPD_FLAG_SMTPUTF8; if (USE_SMTPD_PROXY(state)) state->proxy_mail = mystrdup(STR(state->buffer)); if (var_smtpd_delay_open == 0 && mail_open_stream(state) < 0) { --- 2607,2612 ---- *************** *** 3577,3582 **** --- 3579,3585 ---- const char *err = 0; int rate; int smtputf8 = 0; + int saved_flags; /* * The SMTP standard (RFC 821) disallows unquoted special characters in *************** *** 3663,3672 **** } } /* Use state->addr_buf, with the unquoted result from extract_addr() */ ! if (SMTPD_STAND_ALONE(state) == 0 ! && (err = smtpd_check_rcpt(state, STR(state->addr_buf))) != 0) { ! smtpd_chat_reply(state, "%s", err); ! return (-1); } /* --- 3666,3682 ---- } } /* Use state->addr_buf, with the unquoted result from extract_addr() */ ! if (SMTPD_STAND_ALONE(state) == 0) { ! /* Fix 20161206: allow UTF8 in smtpd_recipient_restrictions. */ ! saved_flags = state->flags; ! if (smtputf8) ! state->flags |= SMTPD_FLAG_SMTPUTF8; ! err = smtpd_check_rcpt(state, STR(state->addr_buf)); ! state->flags = saved_flags; ! if (err != 0) { ! smtpd_chat_reply(state, "%s", err); ! return (-1); ! } } /* *************** *** 5742,5747 **** --- 5752,5758 ---- 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-3.1.3/src/smtpd/smtpd_check.c ./src/smtpd/smtpd_check.c *** /var/tmp/postfix-3.1.3/src/smtpd/smtpd_check.c 2016-02-15 12:06:11.000000000 -0500 --- ./src/smtpd/smtpd_check.c 2017-01-01 12:48:24.000000000 -0500 *************** *** 9,15 **** /* /* void smtpd_check_init() /* ! /* int smtpd_check_addr(address, smtputf8) /* const char *address; /* int smtputf8; /* --- 9,16 ---- /* /* void smtpd_check_init() /* ! /* int smtpd_check_addr(sender, address, smtputf8) ! /* const char *sender; /* const char *address; /* int smtputf8; /* *************** *** 57,63 **** /* once during the process life time. /* /* smtpd_check_addr() sanity checks an email address and returns ! /* non-zero in case of badness. /* /* smtpd_check_rewrite() should be called before opening a queue /* file or proxy connection, in order to establish the proper --- 58,66 ---- /* once during the process life time. /* /* smtpd_check_addr() sanity checks an email address and returns ! /* non-zero in case of badness. The sender argument provides sender ! /* context for address resolution and caching, or a null pointer ! /* if information is unavailable. /* /* smtpd_check_rewrite() should be called before opening a queue /* file or proxy connection, in order to establish the proper *************** *** 278,283 **** --- 281,287 ---- * 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; *************** *** 346,352 **** */ static int check_sender_rcpt_maps(SMTPD_STATE *, const char *); static int check_recipient_rcpt_maps(SMTPD_STATE *, const char *); ! static int check_rcpt_maps(SMTPD_STATE *, const char *, const char *); /* * Tempfail actions; --- 350,357 ---- */ static int check_sender_rcpt_maps(SMTPD_STATE *, const char *); static int check_recipient_rcpt_maps(SMTPD_STATE *, const char *); ! static int check_rcpt_maps(SMTPD_STATE *, const char *, const char *, ! const char *); /* * Tempfail actions; *************** *** 737,742 **** --- 742,750 ---- local_rcpt_maps = maps_create(VAR_LOCAL_RCPT_MAPS, var_local_rcpt_maps, DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX | DICT_FLAG_UTF8_REQUEST); + send_canon_maps = maps_create(VAR_SEND_CANON_MAPS, var_send_canon_maps, + DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX + | DICT_FLAG_UTF8_REQUEST); rcpt_canon_maps = maps_create(VAR_RCPT_CANON_MAPS, var_rcpt_canon_maps, DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX | DICT_FLAG_UTF8_REQUEST); *************** *** 1609,1615 **** /* * Resolve the address. */ ! reply = smtpd_resolve_addr(recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); --- 1617,1623 ---- /* * Resolve the address. */ ! reply = smtpd_resolve_addr(state->sender, recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); *************** *** 1904,1910 **** /* * Resolve the address. */ ! reply = smtpd_resolve_addr(recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); --- 1912,1918 ---- /* * Resolve the address. */ ! reply = smtpd_resolve_addr(state->sender, recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); *************** *** 2092,2098 **** /* * Resolve the address. */ ! reply = smtpd_resolve_addr(addr); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, addr); --- 2100,2107 ---- /* * Resolve the address. */ ! reply = smtpd_resolve_addr(strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? ! state->recipient : state->sender, addr); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, addr); *************** *** 3147,3153 **** /* * Resolve the address. */ ! reply = smtpd_resolve_addr(addr); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, addr); --- 3156,3163 ---- /* * Resolve the address. */ ! reply = smtpd_resolve_addr(strcmp(reply_class, SMTPD_NAME_SENDER) == 0 ? ! state->recipient : state->sender, addr); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, addr); *************** *** 3798,3804 **** * Reject if the client is logged in and does not own the sender address. */ if (smtpd_sender_login_maps && state->sasl_username) { ! reply = smtpd_resolve_addr(sender); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, sender); if ((owners = check_mail_addr_find(state, sender, smtpd_sender_login_maps, --- 3808,3814 ---- * Reject if the client is logged in and does not own the sender address. */ if (smtpd_sender_login_maps && state->sasl_username) { ! reply = smtpd_resolve_addr(state->recipient, sender); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, sender); if ((owners = check_mail_addr_find(state, sender, smtpd_sender_login_maps, *************** *** 3832,3838 **** * owner. */ if (smtpd_sender_login_maps && !state->sasl_username) { ! reply = smtpd_resolve_addr(sender); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, sender); if (check_mail_addr_find(state, sender, smtpd_sender_login_maps, --- 3842,3848 ---- * owner. */ if (smtpd_sender_login_maps && !state->sasl_username) { ! reply = smtpd_resolve_addr(state->recipient, sender); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, sender); if (check_mail_addr_find(state, sender, smtpd_sender_login_maps, *************** *** 4646,4652 **** /* smtpd_check_addr - address sanity check */ ! int smtpd_check_addr(const char *addr, int smtputf8) { const RESOLVE_REPLY *resolve_reply; const char *myname = "smtpd_check_addr"; --- 4656,4662 ---- /* smtpd_check_addr - address sanity check */ ! int smtpd_check_addr(const char *sender, const char *addr, int smtputf8) { const RESOLVE_REPLY *resolve_reply; const char *myname = "smtpd_check_addr"; *************** *** 4662,4668 **** */ if (addr == 0 || *addr == 0) return (0); ! resolve_reply = smtpd_resolve_addr(addr); if (resolve_reply->flags & RESOLVE_FLAG_ERROR) return (-1); --- 4672,4678 ---- */ if (addr == 0 || *addr == 0) return (0); ! resolve_reply = smtpd_resolve_addr(sender, addr); if (resolve_reply->flags & RESOLVE_FLAG_ERROR) return (-1); *************** *** 5072,5078 **** if (state->warn_if_reject == 0) /* We really validate the recipient address. */ state->recipient_rcptmap_checked = 1; ! return (check_rcpt_maps(state, recipient, SMTPD_NAME_RECIPIENT)); } /* check_sender_rcpt_maps - generic_checks() sender table check */ --- 5082,5089 ---- if (state->warn_if_reject == 0) /* We really validate the recipient address. */ state->recipient_rcptmap_checked = 1; ! return (check_rcpt_maps(state, state->sender, recipient, ! SMTPD_NAME_RECIPIENT)); } /* check_sender_rcpt_maps - generic_checks() sender table check */ *************** *** 5091,5114 **** if (state->warn_if_reject == 0) /* We really validate the sender address. */ state->sender_rcptmap_checked = 1; ! return (check_rcpt_maps(state, sender, SMTPD_NAME_SENDER)); } /* check_rcpt_maps - generic_checks() interface for recipient table check */ ! static int check_rcpt_maps(SMTPD_STATE *state, const char *recipient, const char *reply_class) { const RESOLVE_REPLY *reply; DSN_SPLIT dp; if (msg_verbose) ! msg_info(">>> CHECKING RECIPIENT MAPS <<<"); /* * Resolve the address. */ ! reply = smtpd_resolve_addr(recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); --- 5102,5127 ---- if (state->warn_if_reject == 0) /* We really validate the sender address. */ state->sender_rcptmap_checked = 1; ! return (check_rcpt_maps(state, state->recipient, sender, ! SMTPD_NAME_SENDER)); } /* check_rcpt_maps - generic_checks() interface for recipient table check */ ! static int check_rcpt_maps(SMTPD_STATE *state, const char *sender, ! const char *recipient, const char *reply_class) { const RESOLVE_REPLY *reply; DSN_SPLIT dp; if (msg_verbose) ! msg_info(">>> CHECKING %s VALIDATION MAPS <<<", reply_class); /* * Resolve the address. */ ! reply = smtpd_resolve_addr(sender, recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); *************** *** 5129,5134 **** --- 5142,5149 ---- * 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); *************** *** 5476,5481 **** --- 5491,5497 ---- 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; *************** *** 5526,5531 **** --- 5542,5548 ---- 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, *************** *** 6077,6082 **** --- 6094,6115 ---- 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 | DICT_FLAG_UTF8_REQUEST); + 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 | DICT_FLAG_UTF8_REQUEST); + 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-3.1.3/src/smtpd/smtpd_check.h ./src/smtpd/smtpd_check.h *** /var/tmp/postfix-3.1.3/src/smtpd/smtpd_check.h 2014-07-15 08:53:48.000000000 -0400 --- ./src/smtpd/smtpd_check.h 2017-01-01 12:22:54.000000000 -0500 *************** *** 13,19 **** * External interface. */ extern void smtpd_check_init(void); ! extern int smtpd_check_addr(const char *, int); extern char *smtpd_check_rewrite(SMTPD_STATE *); extern char *smtpd_check_client(SMTPD_STATE *); extern char *smtpd_check_helo(SMTPD_STATE *, char *); --- 13,19 ---- * External interface. */ extern void smtpd_check_init(void); ! extern int smtpd_check_addr(const char *, const char *, int); extern char *smtpd_check_rewrite(SMTPD_STATE *); extern char *smtpd_check_client(SMTPD_STATE *); extern char *smtpd_check_helo(SMTPD_STATE *, char *); diff -cr --new-file /var/tmp/postfix-3.1.3/src/smtpd/smtpd_milter.c ./src/smtpd/smtpd_milter.c *** /var/tmp/postfix-3.1.3/src/smtpd/smtpd_milter.c 2016-01-23 19:43:31.000000000 -0500 --- ./src/smtpd/smtpd_milter.c 2017-01-01 12:22:54.000000000 -0500 *************** *** 157,163 **** return (0); if (state->sender[0] == 0) return (""); ! reply = smtpd_resolve_addr(state->sender); /* Sendmail 8.13 does not externalize the null string. */ if (STR(reply->recipient)[0]) quote_821_local(state->expand_buf, STR(reply->recipient)); --- 157,163 ---- return (0); if (state->sender[0] == 0) return (""); ! reply = smtpd_resolve_addr(state->recipient, state->sender); /* Sendmail 8.13 does not externalize the null string. */ if (STR(reply->recipient)[0]) quote_821_local(state->expand_buf, STR(reply->recipient)); *************** *** 168,180 **** if (strcmp(name, S8_MAC_MAIL_HOST) == 0) { if (state->sender == 0) return (0); ! reply = smtpd_resolve_addr(state->sender); return (STR(reply->nexthop)); } if (strcmp(name, S8_MAC_MAIL_MAILER) == 0) { if (state->sender == 0) return (0); ! reply = smtpd_resolve_addr(state->sender); return (STR(reply->transport)); } --- 168,180 ---- if (strcmp(name, S8_MAC_MAIL_HOST) == 0) { if (state->sender == 0) return (0); ! reply = smtpd_resolve_addr(state->recipient, state->sender); return (STR(reply->nexthop)); } if (strcmp(name, S8_MAC_MAIL_MAILER) == 0) { if (state->sender == 0) return (0); ! reply = smtpd_resolve_addr(state->recipient, state->sender); return (STR(reply->transport)); } *************** *** 192,198 **** cp = split_at(STR(state->expand_buf), ' '); return (cp ? split_at(cp, ' ') : cp); } ! reply = smtpd_resolve_addr(state->recipient); /* Sendmail 8.13 does not externalize the null string. */ if (STR(reply->recipient)[0]) quote_821_local(state->expand_buf, STR(reply->recipient)); --- 192,198 ---- cp = split_at(STR(state->expand_buf), ' '); return (cp ? split_at(cp, ' ') : cp); } ! reply = smtpd_resolve_addr(state->sender, state->recipient); /* Sendmail 8.13 does not externalize the null string. */ if (STR(reply->recipient)[0]) quote_821_local(state->expand_buf, STR(reply->recipient)); *************** *** 209,215 **** (void) split_at(STR(state->expand_buf), ' '); return (STR(state->expand_buf)); } ! reply = smtpd_resolve_addr(state->recipient); return (STR(reply->nexthop)); } if (strcmp(name, S8_MAC_RCPT_MAILER) == 0) { --- 209,215 ---- (void) split_at(STR(state->expand_buf), ' '); return (STR(state->expand_buf)); } ! reply = smtpd_resolve_addr(state->sender, state->recipient); return (STR(reply->nexthop)); } if (strcmp(name, S8_MAC_RCPT_MAILER) == 0) { *************** *** 217,223 **** return (0); if (state->milter_reject_text) return (S8_RCPT_MAILER_ERROR); ! reply = smtpd_resolve_addr(state->recipient); return (STR(reply->transport)); } return (0); --- 217,223 ---- return (0); if (state->milter_reject_text) return (S8_RCPT_MAILER_ERROR); ! reply = smtpd_resolve_addr(state->sender, state->recipient); return (STR(reply->transport)); } return (0); diff -cr --new-file /var/tmp/postfix-3.1.3/src/smtpd/smtpd_resolve.c ./src/smtpd/smtpd_resolve.c *** /var/tmp/postfix-3.1.3/src/smtpd/smtpd_resolve.c 2015-01-27 15:19:03.000000000 -0500 --- ./src/smtpd/smtpd_resolve.c 2017-01-01 12:22:54.000000000 -0500 *************** *** 9,15 **** /* void smtpd_resolve_init(cache_size) /* int cache_size; /* ! /* const RESOLVE_REPLY *smtpd_resolve_addr(addr) /* const char *addr; /* DESCRIPTION /* This module maintains a resolve client cache that persists --- 9,16 ---- /* void smtpd_resolve_init(cache_size) /* int cache_size; /* ! /* const RESOLVE_REPLY *smtpd_resolve_addr(sender, addr) ! /* const char *sender; /* const char *addr; /* DESCRIPTION /* This module maintains a resolve client cache that persists *************** *** 26,31 **** --- 27,34 ---- /* Arguments: /* .IP cache_size /* The requested cache size. + /* .IP sender + /* The message sender, or null pointer. /* .IP addr /* The address to resolve. /* DIAGNOSTICS *************** *** 56,61 **** --- 59,65 ---- #include #include #include + #include /* Global library. */ *************** *** 70,89 **** static CTABLE *smtpd_resolve_cache; #define STR(x) vstring_str(x) /* resolve_pagein - page in an address resolver result */ ! static void *resolve_pagein(const char *addr, void *unused_context) { static VSTRING *query; RESOLVE_REPLY *reply; ! char *tmp; /* * Initialize on the fly. */ ! if (query == 0) query = vstring_alloc(10); /* * Initialize. --- 74,101 ---- static CTABLE *smtpd_resolve_cache; #define STR(x) vstring_str(x) + #define SENDER_ADDR_JOIN_CHAR '\n' /* resolve_pagein - page in an address resolver result */ ! static void *resolve_pagein(const char *sender_plus_addr, void *unused_context) { + const char myname[] = "resolve_pagein"; static VSTRING *query; + static VSTRING *junk; + static VSTRING *sender_buf; RESOLVE_REPLY *reply; ! const char *sender; ! const char *addr; /* * Initialize on the fly. */ ! if (query == 0) { query = vstring_alloc(10); + junk = vstring_alloc(10); + sender_buf = vstring_alloc(10); + } /* * Initialize. *************** *** 92,104 **** resolve_clnt_init(reply); /* * Resolve the address. */ rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, addr, query); ! resolve_clnt_query(STR(query), reply); ! tmp = mystrdup(STR(reply->recipient)); ! casefold(reply->recipient, tmp); /* XXX */ ! myfree(tmp); /* * Save the result. --- 104,124 ---- resolve_clnt_init(reply); /* + * Split the sender and address. + */ + vstring_strcpy(junk, sender_plus_addr); + sender = STR(junk); + if ((addr = split_at(STR(junk), SENDER_ADDR_JOIN_CHAR)) == 0) + msg_panic("%s: bad search key: \"%s\"", myname, sender_plus_addr); + + /* * Resolve the address. */ + rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, sender, sender_buf); rewrite_clnt_internal(MAIL_ATTR_RWR_LOCAL, addr, query); ! resolve_clnt_query_from(STR(sender_buf), STR(query), reply); ! vstring_strcpy(junk, STR(reply->recipient)); ! casefold(reply->recipient, STR(junk)); /* XXX */ /* * Save the result. *************** *** 136,145 **** resolve_pageout, (void *) 0); } ! /* smtpd_resolve_addr - resolve cached addres */ ! const RESOLVE_REPLY *smtpd_resolve_addr(const char *addr) { /* * Sanity check. --- 156,172 ---- resolve_pageout, (void *) 0); } ! /* smtpd_resolve_addr - resolve cached address */ ! const RESOLVE_REPLY *smtpd_resolve_addr(const char *sender, const char *addr) { + static VSTRING *sender_plus_addr_buf; + + /* + * Initialize on the fly. + */ + if (sender_plus_addr_buf == 0) + sender_plus_addr_buf = vstring_alloc(10); /* * Sanity check. *************** *** 150,154 **** /* * Reply from the read-through cache. */ ! return (const RESOLVE_REPLY *) ctable_locate(smtpd_resolve_cache, addr); } --- 177,185 ---- /* * Reply from the read-through cache. */ ! vstring_sprintf(sender_plus_addr_buf, "%s%c%s", ! sender ? sender : RESOLVE_NULL_FROM, ! SENDER_ADDR_JOIN_CHAR, addr); ! return (const RESOLVE_REPLY *) ! ctable_locate(smtpd_resolve_cache, STR(sender_plus_addr_buf)); } diff -cr --new-file /var/tmp/postfix-3.1.3/src/smtpd/smtpd_resolve.h ./src/smtpd/smtpd_resolve.h *** /var/tmp/postfix-3.1.3/src/smtpd/smtpd_resolve.h 2009-04-26 13:52:34.000000000 -0400 --- ./src/smtpd/smtpd_resolve.h 2017-01-01 12:22:54.000000000 -0500 *************** *** 17,23 **** * External interface. */ extern void smtpd_resolve_init(int); ! extern const RESOLVE_REPLY *smtpd_resolve_addr(const char *); /* LICENSE /* .ad --- 17,23 ---- * External interface. */ extern void smtpd_resolve_init(int); ! extern const RESOLVE_REPLY *smtpd_resolve_addr(const char*, const char *); /* LICENSE /* .ad diff -cr --new-file /var/tmp/postfix-3.1.3/src/virtual/mailbox.c ./src/virtual/mailbox.c *** /var/tmp/postfix-3.1.3/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); }