From e3501bc815ed19d6bdee5ab4d91fcfdbf3edc581 Mon Sep 17 00:00:00 2001
From: Wietse Z Venema
/etc/postfix/reply_filter: + # Some Microsoft servers violate RFC 2554 section 4, causing Postfix + # to complain with "non-empty initial GSSAPI challenge from server" + /^334\s+GSSAPI\s+supported/ 334 ++ +
# Transform garbage into "250-filler..." so that it looks like # one line from a multi-line reply. It does not matter what we # substitute here as long it has the right syntax. The Postfix diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 8baada969..8c2039ecb 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -2633,13 +2633,16 @@ Needed for debugging Postfix daemons with an X\-windows debugger. .IP "\fBMAIL_CONFIG\fR" Needed to make "\fBpostfix \-c\fR" work. .br +.IP "\fBPOSTLOG_HOSTNAME\fR" +Needed to make "\fBmaillog_file\fR" work during daemon +process initialization. +.br .IP "\fBPOSTLOG_SERVICE\fR" Needed to make "\fBmaillog_file\fR" work during daemon process initialization. .br -.IP "\fBPOSTLOG_HOSTNAME\fR" -Needed to make "\fBmaillog_file\fR" work during daemon -process initialization. +.IP "\fBXDG_RUNTIME_DIR\fR" +Needed for debugging Postfix daemons with an XDG\-style debugger. .br .br .PP @@ -7892,6 +7895,14 @@ Examples: .nf .na /etc/postfix/reply_filter: + # Some Microsoft servers violate RFC 2554 section 4, causing Postfix + # to complain with "non\-empty initial GSSAPI challenge from server" + /^334\es+GSSAPI\es+supported/ 334 +.fi +.ad +.PP +.nf +.na # Transform garbage into "250\-filler..." so that it looks like # one line from a multi\-line reply. It does not matter what we # substitute here as long it has the right syntax. The Postfix diff --git a/postfix/mantools/check-spell-proto-html b/postfix/mantools/check-spell-proto-html index b81ce1f97..ffd427f96 100755 --- a/postfix/mantools/check-spell-proto-html +++ b/postfix/mantools/check-spell-proto-html @@ -4,4 +4,4 @@ LANG=C; export LANG -mantools/dehtml proto/*html proto/*.proto | spell | grep -F -vxf proto/stop | grep -F -vxf proto/stop.spell-proto-html +mantools/dehtml proto/*html proto/*.proto | tr '+' ' ' | spell | grep -F -vxf proto/stop | grep -F -vxf proto/stop.spell-proto-html diff --git a/postfix/proto/COMPATIBILITY_README.html b/postfix/proto/COMPATIBILITY_README.html index 000f06269..20d72b423 100644 --- a/postfix/proto/COMPATIBILITY_README.html +++ b/postfix/proto/COMPATIBILITY_README.html @@ -614,7 +614,7 @@ make the backwards-compatible setting "smtp_tlsrpt_skip_reused_handshakes default setting xxx_security_level=(empty)Postfix version 3.11 changes the default value for client TLS -security levels from "empty" to "yes". The backwards-compatibility +security levels from "empty" to "may". The backwards-compatibility safety net is designed to prevent an unexpected change in mail sending behavior when Postfix is updated from an older version.
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index e6aa3680b..0a4a9255e 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -1984,15 +1984,20 @@ environment. Examples of relevant environment variables:
/etc/postfix/reply_filter: + # Some Microsoft servers violate RFC 2554 section 4, causing Postfix + # to complain with "non-empty initial GSSAPI challenge from server" + /^334\s+GSSAPI\s+supported/ 334 ++ +
# Transform garbage into "250-filler..." so that it looks like # one line from a multi-line reply. It does not matter what we # substitute here as long it has the right syntax. The Postfix diff --git a/postfix/proto/stop b/postfix/proto/stop index c09b1c34e..5a7a3b12a 100644 --- a/postfix/proto/stop +++ b/postfix/proto/stop @@ -1683,3 +1683,4 @@ typofix LD PRELOAD rhansen +XDG diff --git a/postfix/proto/stop.double-history b/postfix/proto/stop.double-history index cf5da6405..6fb0842b7 100644 --- a/postfix/proto/stop.double-history +++ b/postfix/proto/stop.double-history @@ -179,3 +179,5 @@ proto proto COMPATIBILITY_README html postconf Makefile in postconf postconf c dict_open Files util dict hc proxymap proxymap c proxymap proxymap c + postmap postmap c postalias postalias c + client Files dict h dict_proxy c proxymap proxymap c diff --git a/postfix/proto/stop.spell-history b/postfix/proto/stop.spell-history index da067ab97..42b996fab 100644 --- a/postfix/proto/stop.spell-history +++ b/postfix/proto/stop.spell-history @@ -106,3 +106,7 @@ Kozmenko Oleksandr Bataille balancers +Unbroke +XDG +ENOTSOCK +Fustà diff --git a/postfix/src/global/dict_proxy.c b/postfix/src/global/dict_proxy.c index 0157d01a2..a0ce1b2e0 100644 --- a/postfix/src/global/dict_proxy.c +++ b/postfix/src/global/dict_proxy.c @@ -113,6 +113,7 @@ static int dict_proxy_sequence(DICT *dict, int function, VSTREAM *stream; int status; int count = 0; + int inst_flags; int request_flags; /* @@ -126,8 +127,8 @@ static int dict_proxy_sequence(DICT *dict, int function, VSTRING_TERMINATE(dict_proxy->reskey); VSTRING_RESET(dict_proxy->result); VSTRING_TERMINATE(dict_proxy->result); - request_flags = dict_proxy->inst_flags - | (dict->flags & DICT_FLAG_RQST_MASK); + inst_flags = dict_proxy->inst_flags; + request_flags = dict->flags; for (;;) { stream = clnt_stream_access(dict_proxy->clnt); errno = 0; @@ -136,15 +137,17 @@ static int dict_proxy_sequence(DICT *dict, int function, || attr_print(stream, ATTR_FLAG_NONE, SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_SEQUENCE), SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name), + SEND_ATTR_INT(MAIL_ATTR_INST_FLAGS, inst_flags), SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags), SEND_ATTR_INT(MAIL_ATTR_FUNC, function), ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), + RECV_ATTR_INT(MAIL_ATTR_FLAGS, &dict->flags), RECV_ATTR_STR(MAIL_ATTR_KEY, dict_proxy->reskey), RECV_ATTR_STR(MAIL_ATTR_VALUE, dict_proxy->result), - ATTR_TYPE_END) != 3) { + ATTR_TYPE_END) != 4) { if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) msg_warn("%s: service %s: %m", myname, dict_proxy->service); } else { @@ -194,6 +197,7 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key) VSTREAM *stream; int status; int count = 0; + int inst_flags; int request_flags; /* @@ -205,8 +209,8 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key) */ VSTRING_RESET(dict_proxy->result); VSTRING_TERMINATE(dict_proxy->result); - request_flags = dict_proxy->inst_flags - | (dict->flags & DICT_FLAG_RQST_MASK); + inst_flags = dict_proxy->inst_flags; + request_flags = dict->flags; for (;;) { stream = clnt_stream_access(dict_proxy->clnt); errno = 0; @@ -215,14 +219,16 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key) || attr_print(stream, ATTR_FLAG_NONE, SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_LOOKUP), SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name), + SEND_ATTR_INT(MAIL_ATTR_INST_FLAGS, inst_flags), SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags), SEND_ATTR_STR(MAIL_ATTR_KEY, key), ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), + RECV_ATTR_INT(MAIL_ATTR_FLAGS, &dict->flags), RECV_ATTR_STR(MAIL_ATTR_VALUE, dict_proxy->result), - ATTR_TYPE_END) != 2) { + ATTR_TYPE_END) != 3) { if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) msg_warn("%s: service %s: %m", myname, dict_proxy->service); } else { @@ -267,6 +273,7 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value) VSTREAM *stream; int status; int count = 0; + int inst_flags; int request_flags; /* @@ -276,8 +283,8 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value) * associated with a specific connection. Each lookup needs to specify * the table and the flags that were specified to dict_proxy_open(). */ - request_flags = dict_proxy->inst_flags - | (dict->flags & DICT_FLAG_RQST_MASK); + inst_flags = dict_proxy->inst_flags; + request_flags = dict->flags; for (;;) { stream = clnt_stream_access(dict_proxy->clnt); errno = 0; @@ -286,6 +293,7 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value) || attr_print(stream, ATTR_FLAG_NONE, SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_UPDATE), SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name), + SEND_ATTR_INT(MAIL_ATTR_INST_FLAGS, inst_flags), SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags), SEND_ATTR_STR(MAIL_ATTR_KEY, key), SEND_ATTR_STR(MAIL_ATTR_VALUE, value), @@ -293,7 +301,8 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value) || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), - ATTR_TYPE_END) != 1) { + RECV_ATTR_INT(MAIL_ATTR_FLAGS, &dict->flags), + ATTR_TYPE_END) != 2) { if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) msg_warn("%s: service %s: %m", myname, dict_proxy->service); } else { @@ -337,6 +346,7 @@ static int dict_proxy_delete(DICT *dict, const char *key) VSTREAM *stream; int status; int count = 0; + int inst_flags; int request_flags; /* @@ -346,8 +356,8 @@ static int dict_proxy_delete(DICT *dict, const char *key) * associated with a specific connection. Each lookup needs to specify * the table and the flags that were specified to dict_proxy_open(). */ - request_flags = dict_proxy->inst_flags - | (dict->flags & DICT_FLAG_RQST_MASK); + inst_flags = dict_proxy->inst_flags; + request_flags = dict->flags; for (;;) { stream = clnt_stream_access(dict_proxy->clnt); errno = 0; @@ -356,13 +366,15 @@ static int dict_proxy_delete(DICT *dict, const char *key) || attr_print(stream, ATTR_FLAG_NONE, SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_DELETE), SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name), + SEND_ATTR_INT(MAIL_ATTR_INST_FLAGS, inst_flags), SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags), SEND_ATTR_STR(MAIL_ATTR_KEY, key), ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), - ATTR_TYPE_END) != 1) { + RECV_ATTR_INT(MAIL_ATTR_FLAGS, &dict->flags), + ATTR_TYPE_END) != 2) { if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT)) msg_warn("%s: service %s: %m", myname, dict_proxy->service); @@ -478,16 +490,20 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags) dict_proxy->dict.delete = dict_proxy_delete; dict_proxy->dict.sequence = dict_proxy_sequence; dict_proxy->dict.close = dict_proxy_close; - dict_proxy->inst_flags = (dict_flags & DICT_FLAG_INST_MASK); + dict_proxy->inst_flags = dict_flags; dict_proxy->reskey = vstring_alloc(10); dict_proxy->result = vstring_alloc(10); dict_proxy->clnt = *pstream; dict_proxy->service = service; +#define DICT_PROXY_ERR_RETURN(d) do { \ + DICT *_d = (d); \ + dict_proxy_close(&dict_proxy->dict); \ + return (_d); \ + } while (0) + /* * Establish initial contact and get the map type specific flags. - * - * XXX Should retrieve flags from local instance. */ for (;;) { stream = clnt_stream_access(dict_proxy->clnt); @@ -496,7 +512,7 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags) || attr_print(stream, ATTR_FLAG_NONE, SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_OPEN), SEND_ATTR_STR(MAIL_ATTR_TABLE, dict_proxy->dict.name), - SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict_proxy->inst_flags), + SEND_ATTR_INT(MAIL_ATTR_INST_FLAGS, dict_proxy->inst_flags), ATTR_TYPE_END) != 0 || vstream_fflush(stream) || attr_scan(stream, ATTR_FLAG_STRICT, @@ -512,14 +528,17 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags) dict_flags_str(server_flags)); switch (status) { case PROXY_STAT_BAD: - msg_fatal("%s open failed for table \"%s\": invalid request", - dict_proxy->service, dict_proxy->dict.name); + DICT_PROXY_ERR_RETURN(dict_surrogate(DICT_TYPE_PROXY, + dict_proxy->dict.name, open_flags, dict_flags, + "%s open failed for table \"%s\": invalid request", + dict_proxy->service, dict_proxy->dict.name)); case PROXY_STAT_DENY: - msg_fatal("%s service is not configured for table \"%s\"", - dict_proxy->service, dict_proxy->dict.name); + DICT_PROXY_ERR_RETURN(dict_surrogate(DICT_TYPE_PROXY, + dict_proxy->dict.name, open_flags, dict_flags, + "%s service is not configured for table \"%s\"", + dict_proxy->service, dict_proxy->dict.name)); case PROXY_STAT_OK: - dict_proxy->dict.flags = (dict_flags & ~DICT_FLAG_IMPL_MASK) - | (server_flags & DICT_FLAG_IMPL_MASK); + dict_proxy->dict.flags = server_flags; return (&dict_proxy->dict); default: msg_warn("%s open failed for table \"%s\": unexpected status %d", diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 690256a60..cf7d791ea 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -2663,7 +2663,8 @@ extern int var_fflush_refresh; #define VAR_IMPORT_ENVIRON "import_environment" #define DEF_IMPORT_ENVIRON "MAIL_CONFIG MAIL_DEBUG MAIL_LOGTAG " \ "TZ XAUTHORITY DISPLAY LANG=C " \ - "POSTLOG_SERVICE POSTLOG_HOSTNAME" + "POSTLOG_SERVICE POSTLOG_HOSTNAME" \ + "XDG_RUNTIME_DIR" extern char *var_import_environ; #define VAR_EXPORT_ENVIRON "export_environment" diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index 798de6694..d784ce42d 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -210,6 +210,8 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_COMPAT_LEVEL "compatibility_level" #define MAIL_ATTR_MAIL_VERSION "mail_version" +#define MAIL_ATTR_INST_FLAGS "instance_flags" + /* * Suffixes for sender_name, sender_domain etc. */ diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index f19314a40..a1d0ccefd 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20250709" +#define MAIL_RELEASE_DATE "20250713" #define MAIL_VERSION_NUMBER "3.11" #ifdef SNAPSHOT diff --git a/postfix/src/master/event_server.c b/postfix/src/master/event_server.c index 9802bdf2f..30e80ba5e 100644 --- a/postfix/src/master/event_server.c +++ b/postfix/src/master/event_server.c @@ -273,6 +273,7 @@ static unsigned event_server_generation; static void (*event_server_pre_disconn) (VSTREAM *, char *, char **); static void (*event_server_slow_exit) (char *, char **); static int event_server_watchdog = 1000; +static int event_server_drain_was_called = 0; /* event_server_exit - normal termination */ @@ -327,6 +328,9 @@ int event_server_drain(void) const char *myname = "event_server_drain"; int fd; + if (event_server_drain_was_called) + return; + switch (fork()) { /* Try again later. */ case -1: @@ -343,6 +347,7 @@ int event_server_drain(void) msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd); } var_use_limit = 1; + event_server_drain_was_called = 1; return (0); /* Let the master start a new process. */ default: @@ -445,6 +450,9 @@ static void event_server_accept_local(int unused_event, void *context) int time_left = -1; int fd; + if (event_server_drain_was_called) + return; + /* * Be prepared for accept() to fail because some other process already * got the connection (the number of processes competing for clients is @@ -457,6 +465,8 @@ static void event_server_accept_local(int unused_event, void *context) if (event_server_pre_accept) event_server_pre_accept(event_server_name, event_server_argv); + if (event_server_drain_was_called) + return; fd = LOCAL_ACCEPT(listen_fd); if (event_server_lock != 0 && myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK, @@ -483,6 +493,9 @@ static void event_server_accept_pass(int unused_event, void *context) int fd; HTABLE *attr = 0; + if (event_server_drain_was_called) + return; + /* * Be prepared for accept() to fail because some other process already * got the connection (the number of processes competing for clients is @@ -495,6 +508,8 @@ static void event_server_accept_pass(int unused_event, void *context) if (event_server_pre_accept) event_server_pre_accept(event_server_name, event_server_argv); + if (event_server_drain_was_called) + return; fd = pass_accept_attr(listen_fd, &attr); if (event_server_lock != 0 && myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK, @@ -520,6 +535,9 @@ static void event_server_accept_inet(int unused_event, void *context) int time_left = -1; int fd; + if (event_server_drain_was_called) + return; + /* * Be prepared for accept() to fail because some other process already * got the connection (the number of processes competing for clients is @@ -532,6 +550,8 @@ static void event_server_accept_inet(int unused_event, void *context) if (event_server_pre_accept) event_server_pre_accept(event_server_name, event_server_argv); + if (event_server_drain_was_called) + return; fd = inet_accept(listen_fd); if (event_server_lock != 0 && myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK, diff --git a/postfix/src/master/multi_server.c b/postfix/src/master/multi_server.c index 6150f229a..51004d6d0 100644 --- a/postfix/src/master/multi_server.c +++ b/postfix/src/master/multi_server.c @@ -260,6 +260,7 @@ static VSTREAM *multi_server_lock; static int multi_server_in_flow_delay; static unsigned multi_server_generation; static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **); +static int multi_server_drain_was_called = 0; /* multi_server_exit - normal termination */ @@ -295,6 +296,9 @@ int multi_server_drain(void) const char *myname = "multi_server_drain"; int fd; + if (multi_server_drain_was_called) + return; + switch (fork()) { /* Try again later. */ case -1: @@ -311,6 +315,7 @@ int multi_server_drain(void) msg_warn("%s: dup2(%d, %d): %m", myname, STDIN_FILENO, fd); } var_use_limit = 1; + multi_server_drain_was_called = 1; return (0); /* Let the master start a new process. */ default: @@ -429,6 +434,9 @@ static void multi_server_accept_local(int unused_event, void *context) int time_left = -1; int fd; + if (multi_server_drain_was_called) + return; + /* * Be prepared for accept() to fail because some other process already * got the connection (the number of processes competing for clients is @@ -441,6 +449,8 @@ static void multi_server_accept_local(int unused_event, void *context) if (multi_server_pre_accept) multi_server_pre_accept(multi_server_name, multi_server_argv); + if (multi_server_drain_was_called) + return; fd = LOCAL_ACCEPT(listen_fd); if (multi_server_lock != 0 && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK, @@ -467,6 +477,9 @@ static void multi_server_accept_pass(int unused_event, void *context) int fd; HTABLE *attr = 0; + if (multi_server_drain_was_called) + return; + /* * Be prepared for accept() to fail because some other process already * got the connection (the number of processes competing for clients is @@ -479,6 +492,8 @@ static void multi_server_accept_pass(int unused_event, void *context) if (multi_server_pre_accept) multi_server_pre_accept(multi_server_name, multi_server_argv); + if (multi_server_drain_was_called) + return; fd = pass_accept_attr(listen_fd, &attr); if (multi_server_lock != 0 && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK, @@ -504,6 +519,9 @@ static void multi_server_accept_inet(int unused_event, void *context) int time_left = -1; int fd; + if (multi_server_drain_was_called) + return; + /* * Be prepared for accept() to fail because some other process already * got the connection (the number of processes competing for clients is @@ -516,6 +534,8 @@ static void multi_server_accept_inet(int unused_event, void *context) if (multi_server_pre_accept) multi_server_pre_accept(multi_server_name, multi_server_argv); + if (multi_server_drain_was_called) + return; fd = inet_accept(listen_fd); if (multi_server_lock != 0 && myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK, diff --git a/postfix/src/postalias/postalias.c b/postfix/src/postalias/postalias.c index c17b6a1d6..9e77a6b20 100644 --- a/postfix/src/postalias/postalias.c +++ b/postfix/src/postalias/postalias.c @@ -690,8 +690,6 @@ static void postalias_seq(const char *map_type, const char *map_name, const char *value; int func; - if (strcmp(map_type, DICT_TYPE_PROXY) == 0) - msg_fatal("can't sequence maps via the proxy service"); dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags); for (func = DICT_SEQ_FUN_FIRST; /* void */ ; func = DICT_SEQ_FUN_NEXT) { if (dict_seq(dict, func, &key, &value) != 0) diff --git a/postfix/src/postmap/postmap.c b/postfix/src/postmap/postmap.c index 9e8c78381..8f4a83c37 100644 --- a/postfix/src/postmap/postmap.c +++ b/postfix/src/postmap/postmap.c @@ -899,8 +899,6 @@ static void postmap_seq(const char *map_type, const char *map_name, const char *value; int func; - if (strcmp(map_type, DICT_TYPE_PROXY) == 0) - msg_fatal("can't sequence maps via the proxy service"); dict = dict_open3(map_type, map_name, O_RDONLY, dict_flags); for (func = DICT_SEQ_FUN_FIRST; /* void */ ; func = DICT_SEQ_FUN_NEXT) { if (dict_seq(dict, func, &key, &value) != 0) diff --git a/postfix/src/proxymap/proxymap.c b/postfix/src/proxymap/proxymap.c index 3a00c33c1..270e491a0 100644 --- a/postfix/src/proxymap/proxymap.c +++ b/postfix/src/proxymap/proxymap.c @@ -320,7 +320,7 @@ static char *get_nested_dict_name(char *type_name) /* proxy_map_find - look up or open table */ -static DICT *proxy_map_find(const char *map_type_name, int request_flags, +static DICT *proxy_map_find(const char *map_type_name, int inst_flags, int *statp) { DICT *dict; @@ -354,26 +354,12 @@ static DICT *proxy_map_find(const char *map_type_name, int request_flags, /* * Open one instance of a map for each combination of name+flags. - * - * Assume that a map instance can be shared among clients with different - * paranoia flag settings and with different map lookup flag settings. - * - * XXX The open() flags are passed implicitly, via the selection of the - * service name. For a more sophisticated interface, appropriate subsets - * of open() flags should be received directly from the client. */ - vstring_sprintf(map_type_name_flags, "%s:%s", map_type_name, - dict_flags_str(request_flags & DICT_FLAG_INST_MASK)); - if (msg_verbose) - msg_info("proxy_map_find: %s", STR(map_type_name_flags)); - if ((dict = dict_handle(STR(map_type_name_flags))) == 0) { - dict = dict_open(map_type_name, proxy_writer ? - WRITE_OPEN_FLAGS : READ_OPEN_FLAGS, - request_flags); - if (dict == 0) - msg_panic("proxy_map_find: dict_open null result"); - dict_register(STR(map_type_name_flags), dict); - } + dict = dict_open(map_type_name, proxy_writer ? + WRITE_OPEN_FLAGS : READ_OPEN_FLAGS, + inst_flags); + if (dict == 0) + msg_panic("proxy_map_find: dict_open null result"); dict->error = 0; return (dict); } @@ -382,6 +368,7 @@ static DICT *proxy_map_find(const char *map_type_name, int request_flags, static void proxymap_sequence_service(VSTREAM *client_stream) { + int inst_flags; int request_flags; DICT *dict; int request_func; @@ -395,19 +382,19 @@ static void proxymap_sequence_service(VSTREAM *client_stream) */ if (attr_scan(client_stream, ATTR_FLAG_STRICT, RECV_ATTR_STR(MAIL_ATTR_TABLE, request_map), + RECV_ATTR_INT(MAIL_ATTR_INST_FLAGS, &inst_flags), RECV_ATTR_INT(MAIL_ATTR_FLAGS, &request_flags), RECV_ATTR_INT(MAIL_ATTR_FUNC, &request_func), - ATTR_TYPE_END) != 3 + ATTR_TYPE_END) != 4 || (request_func != DICT_SEQ_FUN_FIRST && request_func != DICT_SEQ_FUN_NEXT)) { reply_status = PROXY_STAT_BAD; reply_key = reply_value = ""; - } else if ((dict = proxy_map_find(STR(request_map), request_flags, + } else if ((dict = proxy_map_find(STR(request_map), inst_flags, &reply_status)) == 0) { reply_key = reply_value = ""; } else { - dict->flags = ((dict->flags & ~DICT_FLAG_RQST_MASK) - | (request_flags & DICT_FLAG_RQST_MASK)); + dict->flags = request_flags; dict_status = dict_seq(dict, request_func, &reply_key, &reply_value); if (dict_status == 0) { reply_status = PROXY_STAT_OK; @@ -426,6 +413,7 @@ static void proxymap_sequence_service(VSTREAM *client_stream) */ attr_print(client_stream, ATTR_FLAG_NONE, SEND_ATTR_INT(MAIL_ATTR_STATUS, reply_status), + SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict->flags), SEND_ATTR_STR(MAIL_ATTR_KEY, reply_key), SEND_ATTR_STR(MAIL_ATTR_VALUE, reply_value), ATTR_TYPE_END); @@ -435,6 +423,7 @@ static void proxymap_sequence_service(VSTREAM *client_stream) static void proxymap_lookup_service(VSTREAM *client_stream) { + int inst_flags; int request_flags; DICT *dict; const char *reply_value; @@ -445,16 +434,16 @@ static void proxymap_lookup_service(VSTREAM *client_stream) */ if (attr_scan(client_stream, ATTR_FLAG_STRICT, RECV_ATTR_STR(MAIL_ATTR_TABLE, request_map), + RECV_ATTR_INT(MAIL_ATTR_INST_FLAGS, &inst_flags), RECV_ATTR_INT(MAIL_ATTR_FLAGS, &request_flags), RECV_ATTR_STR(MAIL_ATTR_KEY, request_key), - ATTR_TYPE_END) != 3) { + ATTR_TYPE_END) != 4) { reply_status = PROXY_STAT_BAD; reply_value = ""; - } else if ((dict = proxy_map_find(STR(request_map), request_flags, + } else if ((dict = proxy_map_find(STR(request_map), inst_flags, &reply_status)) == 0) { reply_value = ""; - } else if (dict->flags = ((dict->flags & ~DICT_FLAG_RQST_MASK) - | (request_flags & DICT_FLAG_RQST_MASK)), + } else if (dict->flags = request_flags, (reply_value = dict_get(dict, STR(request_key))) != 0) { reply_status = PROXY_STAT_OK; } else if (dict->error == 0) { @@ -471,6 +460,7 @@ static void proxymap_lookup_service(VSTREAM *client_stream) */ attr_print(client_stream, ATTR_FLAG_NONE, SEND_ATTR_INT(MAIL_ATTR_STATUS, reply_status), + SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict->flags), SEND_ATTR_STR(MAIL_ATTR_VALUE, reply_value), ATTR_TYPE_END); } @@ -479,6 +469,7 @@ static void proxymap_lookup_service(VSTREAM *client_stream) static void proxymap_update_service(VSTREAM *client_stream) { + int inst_flags; int request_flags; DICT *dict; int dict_status; @@ -495,21 +486,22 @@ static void proxymap_update_service(VSTREAM *client_stream) */ if (attr_scan(client_stream, ATTR_FLAG_STRICT, RECV_ATTR_STR(MAIL_ATTR_TABLE, request_map), + RECV_ATTR_INT(MAIL_ATTR_INST_FLAGS, &inst_flags), RECV_ATTR_INT(MAIL_ATTR_FLAGS, &request_flags), RECV_ATTR_STR(MAIL_ATTR_KEY, request_key), RECV_ATTR_STR(MAIL_ATTR_VALUE, request_value), - ATTR_TYPE_END) != 4) { + ATTR_TYPE_END) != 5) { reply_status = PROXY_STAT_BAD; } else if (proxy_writer == 0) { msg_warn("refusing %s update request on non-%s service", STR(request_map), MAIL_SERVICE_PROXYWRITE); reply_status = PROXY_STAT_DENY; - } else if ((dict = proxy_map_find(STR(request_map), request_flags, + } else if ((dict = proxy_map_find(STR(request_map), inst_flags, &reply_status)) == 0) { /* void */ ; } else { - dict->flags = ((dict->flags & ~DICT_FLAG_RQST_MASK) - | (request_flags & DICT_FLAG_RQST_MASK) + /* Sync the table now. Don't abort on duplicate update. */ + dict->flags = (request_flags | DICT_FLAG_SYNC_UPDATE | DICT_FLAG_DUP_REPLACE); dict_status = dict_put(dict, STR(request_key), STR(request_value)); if (dict_status == 0) { @@ -527,6 +519,7 @@ static void proxymap_update_service(VSTREAM *client_stream) */ attr_print(client_stream, ATTR_FLAG_NONE, SEND_ATTR_INT(MAIL_ATTR_STATUS, reply_status), + SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict->flags), ATTR_TYPE_END); } @@ -534,6 +527,7 @@ static void proxymap_update_service(VSTREAM *client_stream) static void proxymap_delete_service(VSTREAM *client_stream) { + int inst_flags; int request_flags; DICT *dict; int dict_status; @@ -547,20 +541,21 @@ static void proxymap_delete_service(VSTREAM *client_stream) */ if (attr_scan(client_stream, ATTR_FLAG_STRICT, RECV_ATTR_STR(MAIL_ATTR_TABLE, request_map), + RECV_ATTR_INT(MAIL_ATTR_INST_FLAGS, &inst_flags), RECV_ATTR_INT(MAIL_ATTR_FLAGS, &request_flags), RECV_ATTR_STR(MAIL_ATTR_KEY, request_key), - ATTR_TYPE_END) != 3) { + ATTR_TYPE_END) != 4) { reply_status = PROXY_STAT_BAD; } else if (proxy_writer == 0) { msg_warn("refusing %s delete request on non-%s service", STR(request_map), MAIL_SERVICE_PROXYWRITE); reply_status = PROXY_STAT_DENY; - } else if ((dict = proxy_map_find(STR(request_map), request_flags, + } else if ((dict = proxy_map_find(STR(request_map), inst_flags, &reply_status)) == 0) { /* void */ ; } else { - dict->flags = ((dict->flags & ~DICT_FLAG_RQST_MASK) - | (request_flags & DICT_FLAG_RQST_MASK) + /* Sync the table now. There is no close() request. */ + dict->flags = (request_flags | DICT_FLAG_SYNC_UPDATE); dict_status = dict_del(dict, STR(request_key)); if (dict_status == 0) { @@ -578,6 +573,7 @@ static void proxymap_delete_service(VSTREAM *client_stream) */ attr_print(client_stream, ATTR_FLAG_NONE, SEND_ATTR_INT(MAIL_ATTR_STATUS, reply_status), + SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict->flags), ATTR_TYPE_END); } @@ -585,7 +581,7 @@ static void proxymap_delete_service(VSTREAM *client_stream) static void proxymap_open_service(VSTREAM *client_stream) { - int request_flags; + int inst_flags; DICT *dict; int reply_status; int reply_flags; @@ -595,11 +591,11 @@ static void proxymap_open_service(VSTREAM *client_stream) */ if (attr_scan(client_stream, ATTR_FLAG_STRICT, RECV_ATTR_STR(MAIL_ATTR_TABLE, request_map), - RECV_ATTR_INT(MAIL_ATTR_FLAGS, &request_flags), + RECV_ATTR_INT(MAIL_ATTR_INST_FLAGS, &inst_flags), ATTR_TYPE_END) != 2) { reply_status = PROXY_STAT_BAD; reply_flags = 0; - } else if ((dict = proxy_map_find(STR(request_map), request_flags, + } else if ((dict = proxy_map_find(STR(request_map), inst_flags, &reply_status)) == 0) { reply_flags = 0; } else { @@ -843,14 +839,6 @@ int main(int argc, char **argv) */ MAIL_VERSION_STAMP_ALLOCATE; - /* - * Workaround for programs that make explicit dict_register() calls with - * a table that is already registered under a different name. This is - * safe only in programs that do not unregister or close a table that is - * registered with multiple names. - */ - dict_allow_multiple_dict_register_names = 1; - /* * XXX When invoked with the master.cf service name "proxywrite", the * proxymap daemon will allow update requests. To update a table that is diff --git a/postfix/src/util/dict.c b/postfix/src/util/dict.c index 87dee602f..943772325 100644 --- a/postfix/src/util/dict.c +++ b/postfix/src/util/dict.c @@ -82,8 +82,6 @@ /* const char *name, /* int open_flags, /* int dict_flags) -/* -/* int dict_allow_multiple_dict_register_names; /* DESCRIPTION /* This module maintains a collection of name-value dictionaries. /* Each dictionary has its own name and has its own methods to read @@ -187,14 +185,6 @@ /* This encourages consistent sharing of dictionary instances that /* have the exact same type:name and (initial) flags. The result /* value is the string value of the \fIout\fR VSTRING buffer. -/* -/* dict_allow_multiple_dict_register_names enables a temporary -/* workaround for programs that make explicit dict_register() -/* calls with a table that is already registered under a different -/* name. Setting this to non-zero allows a dictionary to be -/* registered under multiple names. This workaround is safe only -/* in programs that do not unregister or close a table that is -/* registered with multiple names. /* TRUST AND PROVENANCE /* .ad /* .fi @@ -339,14 +329,6 @@ typedef struct { dict = node->dict; \ } while (0) - /* - * Workaround for programs that make explicit dict_register() calls with - * tables that are already registered under a different name. This is safe - * only in programs that do not unregister or close a table that is - * registered with multiple names. - */ -int dict_allow_multiple_dict_register_names = 0; - #define STR(x) vstring_str(x) /* dict_register_close - trigger dictionary cleanup */ @@ -367,8 +349,7 @@ void dict_register(const char *dict_name, DICT *dict_info) /* * Enforce referential integrity. */ - if (dict_allow_multiple_dict_register_names == 0 - && dict_info->reg_name && strcmp(dict_name, dict_info->reg_name) != 0) + if (dict_info->reg_name && strcmp(dict_name, dict_info->reg_name) != 0) msg_panic("%s: '%s:%s' is already registered under '%s' and cannot " "also be registered under '%s'", myname, dict_info->type, dict_info->name, dict_info->reg_name, dict_name); diff --git a/postfix/src/util/dict.h b/postfix/src/util/dict.h index 595f18ed0..36def9b3c 100644 --- a/postfix/src/util/dict.h +++ b/postfix/src/util/dict.h @@ -141,32 +141,12 @@ extern void dict_free(DICT *); * The subsets of flags that control how a map is used. These are relevant * mainly for proxymap support. Note: some categories overlap. * - * DICT_FLAG_IMPL_MASK - flags that are set by the map implementation itself. - * * DICT_FLAG_PARANOID - requestor flags that forbid the use of insecure map * types for security-sensitive operations. These flags are checked by the * map implementation itself upon open, lookup etc. requests. - * - * DICT_FLAG_RQST_MASK - all requestor flags, including paranoid flags, that - * the requestor may change between open, lookup etc. requests. These - * specify requestor properties, not map properties. - * - * DICT_FLAG_INST_MASK - none of the above flags. The requestor may not change - * these flags between open, lookup, etc. requests (although a map may make - * changes to its copy of some of these flags). The proxymap server opens - * only one map instance for all client requests with the same values of - * these flags, and the proxymap client uses its own saved copy of these - * flags. DICT_FLAG_SRC_RHS_IS_FILE is an example of such a flag. */ #define DICT_FLAG_PARANOID \ (DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY | DICT_FLAG_NO_UNAUTH) -#define DICT_FLAG_IMPL_MASK (DICT_FLAG_FIXED | DICT_FLAG_PATTERN | \ - DICT_FLAG_MULTI_WRITER) -#define DICT_FLAG_RQST_MASK (DICT_FLAG_FOLD_ANY | DICT_FLAG_LOCK | \ - DICT_FLAG_DUP_REPLACE | DICT_FLAG_DUP_WARN | \ - DICT_FLAG_DUP_IGNORE | DICT_FLAG_SYNC_UPDATE | \ - DICT_FLAG_PARANOID | DICT_FLAG_UTF8_MASK) -#define DICT_FLAG_INST_MASK ~(DICT_FLAG_IMPL_MASK | DICT_FLAG_RQST_MASK) /* * Feature tests. @@ -286,14 +266,6 @@ extern DICT *PRINTFLIKE(5, 6) dict_surrogate(const char *, const char *, int, in extern char *dict_make_registered_name(VSTRING *, const char *, int, int); extern char *dict_make_registered_name4(VSTRING *, const char *, const char *, int, int); - /* - * Workaround for programs that make explicit dict_register() calls with a - * table that is already registered under a different name. This is safe - * only in programs that do not unregister or close a table that is - * registered with multiple names. - */ -extern int dict_allow_multiple_dict_register_names; - /* * This name is reserved for matchlist error handling. */ diff --git a/postfix/src/util/dict_alloc.c b/postfix/src/util/dict_alloc.c index d780ecf97..bea8e7d7e 100644 --- a/postfix/src/util/dict_alloc.c +++ b/postfix/src/util/dict_alloc.c @@ -147,7 +147,7 @@ DICT *dict_alloc(const char *dict_type, const char *dict_name, ssize_t size) dict->type = mystrdup(dict_type); dict->name = mystrdup(dict_name); - dict->flags = DICT_FLAG_FIXED; + dict->flags = 0; dict->lookup = dict_default_lookup; dict->update = dict_default_update; dict->delete = dict_default_delete; diff --git a/postfix/src/util/dict_test.c b/postfix/src/util/dict_test.c index bd2cadd4d..26fcd0975 100644 --- a/postfix/src/util/dict_test.c +++ b/postfix/src/util/dict_test.c @@ -146,14 +146,8 @@ void dict_test(int argc, char **argv) vstream_printf("dict flags %s\n", dict_flags_str(dict->flags)); } else if (strcmp(cmd, "masks") == 0 && !key && !value) { - vstream_printf("DICT_FLAG_IMPL_MASK %s\n", - dict_flags_str(DICT_FLAG_IMPL_MASK)); vstream_printf("DICT_FLAG_PARANOID %s\n", dict_flags_str(DICT_FLAG_PARANOID)); - vstream_printf("DICT_FLAG_RQST_MASK %s\n", - dict_flags_str(DICT_FLAG_RQST_MASK)); - vstream_printf("DICT_FLAG_INST_MASK %s\n", - dict_flags_str(DICT_FLAG_INST_MASK)); } else { vstream_printf("usage: %s\n", USAGE); }