Prereq: "3.0.7" diff -cr --new-file /var/tmp/postfix-3.0.7/src/global/mail_version.h ./src/global/mail_version.h *** /var/tmp/postfix-3.0.7/src/global/mail_version.h 2016-10-01 19:26:42.000000000 -0400 --- ./src/global/mail_version.h 2017-01-01 11:48: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.0.7" #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.0.8" #ifdef SNAPSHOT #define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE diff -cr --new-file /var/tmp/postfix-3.0.7/HISTORY ./HISTORY *** /var/tmp/postfix-3.0.7/HISTORY 2016-10-01 19:36:30.000000000 -0400 --- ./HISTORY 2017-01-01 11:38:14.000000000 -0500 *************** *** 21762,21767 **** --- 21762,21793 ---- Portability: OpenBSD 6.0. Files: makedefs, util/sys_defs.h. + 20160618 + + 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 *************** *** 21796,21798 **** --- 21822,21845 ---- 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. + + 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.0.7/src/postscreen/postscreen.c ./src/postscreen/postscreen.c *** /var/tmp/postfix-3.0.7/src/postscreen/postscreen.c 2016-04-11 08:51:26.000000000 -0400 --- ./src/postscreen/postscreen.c 2017-01-01 11:25:53.000000000 -0500 *************** *** 760,765 **** --- 760,766 ---- * 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; *************** *** 773,778 **** --- 774,786 ---- 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); *************** *** 824,829 **** --- 832,838 ---- void *unused_context) { PSC_STATE dummy; + PSC_CLIENT_INFO dummy_client_info; /* * This function is called by the cache cleanup pseudo thread. *************** *** 833,838 **** --- 842,848 ---- * 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.0.7/src/postscreen/postscreen.h ./src/postscreen/postscreen.h *** /var/tmp/postfix-3.0.7/src/postscreen/postscreen.h 2014-12-06 20:35:33.000000000 -0500 --- ./src/postscreen/postscreen.h 2017-01-01 11:25:53.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-3.0.7/src/postscreen/postscreen_early.c ./src/postscreen/postscreen_early.c *** /var/tmp/postfix-3.0.7/src/postscreen/postscreen_early.c 2014-12-06 20:35:33.000000000 -0500 --- ./src/postscreen/postscreen_early.c 2017-01-01 11:25:53.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-3.0.7/src/postscreen/postscreen_misc.c ./src/postscreen/postscreen_misc.c *** /var/tmp/postfix-3.0.7/src/postscreen/postscreen_misc.c 2011-01-02 11:20:40.000000000 -0500 --- ./src/postscreen/postscreen_misc.c 2017-01-01 11:25:53.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.0.7/src/postscreen/postscreen_state.c ./src/postscreen/postscreen_state.c *** /var/tmp/postfix-3.0.7/src/postscreen/postscreen_state.c 2014-12-06 20:35:33.000000000 -0500 --- ./src/postscreen/postscreen_state.c 2017-01-01 11:25:53.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.0.7/src/postscreen/postscreen_tests.c ./src/postscreen/postscreen_tests.c *** /var/tmp/postfix-3.0.7/src/postscreen/postscreen_tests.c 2013-05-12 13:09:08.000000000 -0400 --- ./src/postscreen/postscreen_tests.c 2017-01-01 11:25:53.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.0.7/src/postsuper/postsuper.c ./src/postsuper/postsuper.c *** /var/tmp/postfix-3.0.7/src/postsuper/postsuper.c 2014-10-16 17:58:31.000000000 -0400 --- ./src/postsuper/postsuper.c 2016-11-05 10:49:22.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-3.0.7/src/smtpd/Makefile.in ./src/smtpd/Makefile.in *** /var/tmp/postfix-3.0.7/src/smtpd/Makefile.in 2015-01-27 19:13:12.000000000 -0500 --- ./src/smtpd/Makefile.in 2017-01-01 11:21:44.000000000 -0500 *************** *** 533,538 **** --- 533,539 ---- 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.0.7/src/smtpd/smtpd.c ./src/smtpd/smtpd.c *** /var/tmp/postfix-3.0.7/src/smtpd/smtpd.c 2016-09-11 09:42:48.000000000 -0400 --- ./src/smtpd/smtpd.c 2017-01-01 11:35:27.000000000 -0500 *************** *** 1214,1219 **** --- 1214,1220 ---- 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; *************** *** 2222,2228 **** 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), '?')); --- 2223,2231 ---- 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), '?')); *************** *** 2272,2278 **** char *verp_delims = 0; int rate; int dsn_envid = 0; - int smtputf8 = 0; state->flags &= ~SMTPD_FLAG_SMTPUTF8; state->encoding = 0; --- 2275,2280 ---- *************** *** 2339,2351 **** 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); --- 2341,2355 ---- 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); *************** *** 2545,2552 **** 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) { --- 2549,2554 ---- *************** *** 3519,3524 **** --- 3521,3527 ---- const char *err = 0; int rate; int smtputf8 = 0; + int saved_flags; /* * The SMTP standard (RFC 821) disallows unquoted special characters in *************** *** 3605,3614 **** } } /* 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); } /* --- 3608,3624 ---- } } /* 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); ! } } /* *************** *** 5682,5687 **** --- 5692,5698 ---- 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.0.7/src/smtpd/smtpd_check.c ./src/smtpd/smtpd_check.c *** /var/tmp/postfix-3.0.7/src/smtpd/smtpd_check.c 2015-02-08 12:02:51.000000000 -0500 --- ./src/smtpd/smtpd_check.c 2017-01-01 11:35:27.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; *************** *** 730,735 **** --- 735,743 ---- 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); *************** *** 1595,1601 **** /* * Resolve the address. */ ! reply = smtpd_resolve_addr(recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); --- 1603,1609 ---- /* * Resolve the address. */ ! reply = smtpd_resolve_addr(state->sender, recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); *************** *** 1890,1896 **** /* * Resolve the address. */ ! reply = smtpd_resolve_addr(recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); --- 1898,1904 ---- /* * Resolve the address. */ ! reply = smtpd_resolve_addr(state->sender, recipient); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, recipient); *************** *** 2078,2084 **** /* * Resolve the address. */ ! reply = smtpd_resolve_addr(addr); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, addr); --- 2086,2093 ---- /* * 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); *************** *** 3130,3136 **** /* * Resolve the address. */ ! reply = smtpd_resolve_addr(addr); if (reply->flags & RESOLVE_FLAG_FAIL) reject_dict_retry(state, addr); --- 3139,3146 ---- /* * 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); *************** *** 3781,3787 **** * 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, --- 3791,3797 ---- * 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, *************** *** 3815,3821 **** * 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, --- 3825,3831 ---- * 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, *************** *** 4627,4633 **** /* 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"; --- 4637,4643 ---- /* 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"; *************** *** 4643,4649 **** */ if (addr == 0 || *addr == 0) return (0); ! resolve_reply = smtpd_resolve_addr(addr); if (resolve_reply->flags & RESOLVE_FLAG_ERROR) return (-1); --- 4653,4659 ---- */ if (addr == 0 || *addr == 0) return (0); ! resolve_reply = smtpd_resolve_addr(sender, addr); if (resolve_reply->flags & RESOLVE_FLAG_ERROR) return (-1); *************** *** 5053,5059 **** 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 */ --- 5063,5070 ---- 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 */ *************** *** 5072,5095 **** 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); --- 5083,5108 ---- 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); *************** *** 5110,5115 **** --- 5123,5130 ---- * 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); *************** *** 5456,5461 **** --- 5471,5477 ---- 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; *************** *** 5506,5511 **** --- 5522,5528 ---- 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, *************** *** 6057,6062 **** --- 6074,6095 ---- 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.0.7/src/smtpd/smtpd_check.h ./src/smtpd/smtpd_check.h *** /var/tmp/postfix-3.0.7/src/smtpd/smtpd_check.h 2014-07-15 08:53:48.000000000 -0400 --- ./src/smtpd/smtpd_check.h 2017-01-01 11:21:44.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.0.7/src/smtpd/smtpd_milter.c ./src/smtpd/smtpd_milter.c *** /var/tmp/postfix-3.0.7/src/smtpd/smtpd_milter.c 2015-01-27 14:33:29.000000000 -0500 --- ./src/smtpd/smtpd_milter.c 2017-01-01 11:21:44.000000000 -0500 *************** *** 160,166 **** 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)); --- 160,166 ---- 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)); *************** *** 171,183 **** 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)); } --- 171,183 ---- 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)); } *************** *** 195,201 **** 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)); --- 195,201 ---- 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)); *************** *** 212,218 **** (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) { --- 212,218 ---- (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) { *************** *** 220,226 **** return (0); if (state->milter_reject_text) return (S8_RCPT_MAILER_ERROR); ! reply = smtpd_resolve_addr(state->recipient); return (STR(reply->transport)); } return (0); --- 220,226 ---- 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.0.7/src/smtpd/smtpd_resolve.c ./src/smtpd/smtpd_resolve.c *** /var/tmp/postfix-3.0.7/src/smtpd/smtpd_resolve.c 2015-01-27 15:19:03.000000000 -0500 --- ./src/smtpd/smtpd_resolve.c 2017-01-01 11:21:44.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.0.7/src/smtpd/smtpd_resolve.h ./src/smtpd/smtpd_resolve.h *** /var/tmp/postfix-3.0.7/src/smtpd/smtpd_resolve.h 2009-04-26 13:52:34.000000000 -0400 --- ./src/smtpd/smtpd_resolve.h 2017-01-01 11:21:44.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.0.7/src/virtual/mailbox.c ./src/virtual/mailbox.c *** /var/tmp/postfix-3.0.7/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); }