20030126
- Update: maildir filename algorithm updated according to
+ Update: maildir filename algorithm updated according to
today's version of http://cr.yp.to/proto/maildir.html.
+20030127
+
+ Cleanup: use separate error messages for separate problems
+ with computing the list of SASL authentication mechanisms.
+ File: smtpd/smtpd_sasl_glue.c.
+
+20030130
+
+ Bugfix: allow $name in default time values. File:
+ global/mail_conf_time.c.
+
+20030205
+
+ Feature: allow !, /file/name and map:name in masquerade_exceptions.
+ By Liviu Daia. Files:cleanup_init.c, cleanup.h,
+ cleanup_masquerade.c.
+
+20030219
+
+ Bugfix: the local pickup daemon skipped unterminated records,
+ since they happened to have the same record type code as
+ content filtering instructions. Victor Duchovni. Files:
+ global/rec_type.h, pickup/pickup.c.
+
+ Portability: Postfix could block, and thus not enforce
+ command execution time limits, while delivering mail to
+ command. File: global/pipe_command.c.
+
+ Bugfix: command execution time limits were not enforced
+ because the child process killing code in pipe_command()
+ was running with the wrong privileges. Problem reported by
+ Ben Rosengart, Panix. File: global/pipe_command.c.
+
+ Bugfix: duplicate recipient filtering in the cleanup server
+ did not eliminate virtual expansion duplicates with the
+ same original recipient. File: cleanup/cleanup_out_recipient.c.
+
Open problems:
Med: make qmgr recipient bounce/defer activity asynchronous
all names or addresses of local recipients. A recipient address is
local when the address domain matches $mydestination or $inet_interfaces.
+The right-hand side of the lookup tables is conveniently ignored.
+In the left-hand side, specify a bare username, an @domain.tld
+wild-card, or specify a user@domain.tld address.
+
If the local_recipient_maps parameter value is non-empty, then the
SMTP server will reject for an unknown local recipient mail with
"User unknown in local recipient table".
# to access the passwd file via the proxymap service, in order to
# overcome chroot restrictions. The alternative, having a copy of
# the system passwd file in the chroot jail is just not practical.
+#
+# The right-hand side of the lookup tables is conveniently ignored.
+# In the left-hand side, specify a bare username, an @domain.tld
+# wild-card, or specify a user@domain.tld address.
#
#local_recipient_maps = unix:passwd.byname $alias_maps
#local_recipient_maps = proxy:unix:passwd.byname $alias_maps
#
# If this parameter is defined, then the SMTP server will reject
# mail for unknown relay users. This feature is off by default.
+#
+# The right-hand side of the lookup tables is conveniently ignored.
+# In the left-hand side, specify an @domain.tld wild-card, or specify
+# a user@domain.tld address.
#
#relay_recipient_maps = hash:/etc/postfix/relay_recipients
# names that are not subjected to address masquerading.
#
# By default, address masquerading makes no exceptions.
+#
+# Specify a list of user names, /file/name or type:table patterns,
+# separated by commas and/or whitespace. The list is matched left to
+# right, and the search stops on the first match. Specify !name to
+# exclude a name from the list. A /file/name pattern is replaced by
+# its contents; a type:table is matched when a name matches a lookup
+# key (the right-hand side is ignored). Continue long lines by
+# starting the next line with whitespace.
#
#masquerade_exceptions = root,mailer-daemon
#masquerade_exceptions = root
# - You use the "luser_relay", "mailbox_transport", or "fallback_transport"
# feature of the Postfix local delivery agent (see sample-local.cf).
#
+# Details are described in the LOCAL_RECIPIENT_README file.
+#
# Beware: if the Postfix SMTP server runs chrooted, you probably have
# to access the passwd file via the proxymap service, in order to
# overcome chroot restrictions. The alternative, having a copy of
# the system passwd file in the chroot jail is just not practical.
#
+# The right-hand side of the lookup tables is conveniently ignored.
+# In the left-hand side, specify a bare username, an @domain.tld
+# wild-card, or specify a user@domain.tld address.
+#
#local_recipient_maps =
#local_recipient_maps = unix:passwd.byname $alias_maps
local_recipient_maps = proxy:unix:passwd.byname $alias_maps
# If this parameter is defined, then the SMTP server will reject
# mail for unknown relay users. This feature is off by default.
#
+# The right-hand side of the lookup tables is conveniently ignored.
+# In the left-hand side, specify an @domain.tld wild-card, or specify
+# a user@domain.tld address.
+#
#relay_recipient_maps = hash:/etc/postfix/relay_recipients
#
The <b>masquerade_exceptions</b> configuration parameter specifies
what user names should not be subjected to address masquerading.
-Specify one or more user names separated by whitespace or commas.
+Specify a list of user names, /file/name or type:table patterns,
+separated by commas and/or whitespace. The list is matched left to
+right, and the search stops on the first match. Specify !name to
+exclude a name from the list. A /file/name pattern is replaced by
+its contents; a type:table is matched when a name matches a lookup
+key (the right-hand side is ignored). Continue long lines by
+starting the next line with whitespace.
For example,
<dl>
<dd><b>masquerade_exceptions = root</b>
+<dd><b>masquerade_exceptions = /etc/postfix/masquerade-exceptions</b>
+
</dl>
<p>
cleanup.o: ../../include/mail_stream.h
cleanup.o: ../../include/mime_state.h
cleanup.o: ../../include/header_opts.h
+cleanup.o: ../../include/string_list.h
+cleanup.o: ../../include/match_list.h
+cleanup.o: ../../include/match_ops.h
cleanup_api.o: cleanup_api.c
cleanup_api.o: ../../include/sys_defs.h
cleanup_api.o: ../../include/msg.h
cleanup_api.o: ../../include/mail_conf.h
cleanup_api.o: ../../include/mime_state.h
cleanup_api.o: ../../include/header_opts.h
+cleanup_api.o: ../../include/string_list.h
+cleanup_api.o: ../../include/match_list.h
+cleanup_api.o: ../../include/match_ops.h
cleanup_envelope.o: cleanup_envelope.c
cleanup_envelope.o: ../../include/sys_defs.h
cleanup_envelope.o: ../../include/msg.h
cleanup_envelope.o: ../../include/mail_conf.h
cleanup_envelope.o: ../../include/mime_state.h
cleanup_envelope.o: ../../include/header_opts.h
+cleanup_envelope.o: ../../include/string_list.h
+cleanup_envelope.o: ../../include/match_list.h
+cleanup_envelope.o: ../../include/match_ops.h
cleanup_extracted.o: cleanup_extracted.c
cleanup_extracted.o: ../../include/sys_defs.h
cleanup_extracted.o: ../../include/msg.h
cleanup_extracted.o: ../../include/mail_conf.h
cleanup_extracted.o: ../../include/mime_state.h
cleanup_extracted.o: ../../include/header_opts.h
+cleanup_extracted.o: ../../include/string_list.h
+cleanup_extracted.o: ../../include/match_list.h
+cleanup_extracted.o: ../../include/match_ops.h
cleanup_init.o: cleanup_init.c
cleanup_init.o: ../../include/sys_defs.h
cleanup_init.o: ../../include/msg.h
cleanup_init.o: ../../include/mail_conf.h
cleanup_init.o: ../../include/mime_state.h
cleanup_init.o: ../../include/header_opts.h
+cleanup_init.o: ../../include/string_list.h
+cleanup_init.o: ../../include/match_list.h
+cleanup_init.o: ../../include/match_ops.h
cleanup_map11.o: cleanup_map11.c
cleanup_map11.o: ../../include/sys_defs.h
cleanup_map11.o: ../../include/msg.h
cleanup_map11.o: ../../include/mail_conf.h
cleanup_map11.o: ../../include/mime_state.h
cleanup_map11.o: ../../include/header_opts.h
+cleanup_map11.o: ../../include/string_list.h
+cleanup_map11.o: ../../include/match_list.h
+cleanup_map11.o: ../../include/match_ops.h
cleanup_map1n.o: cleanup_map1n.c
cleanup_map1n.o: ../../include/sys_defs.h
cleanup_map1n.o: ../../include/mymalloc.h
cleanup_map1n.o: ../../include/mail_conf.h
cleanup_map1n.o: ../../include/mime_state.h
cleanup_map1n.o: ../../include/header_opts.h
+cleanup_map1n.o: ../../include/string_list.h
+cleanup_map1n.o: ../../include/match_list.h
+cleanup_map1n.o: ../../include/match_ops.h
cleanup_masquerade.o: cleanup_masquerade.c
cleanup_masquerade.o: ../../include/sys_defs.h
cleanup_masquerade.o: ../../include/msg.h
cleanup_masquerade.o: ../../include/mail_conf.h
cleanup_masquerade.o: ../../include/mime_state.h
cleanup_masquerade.o: ../../include/header_opts.h
+cleanup_masquerade.o: ../../include/string_list.h
+cleanup_masquerade.o: ../../include/match_list.h
+cleanup_masquerade.o: ../../include/match_ops.h
cleanup_message.o: cleanup_message.c
cleanup_message.o: ../../include/sys_defs.h
cleanup_message.o: ../../include/msg.h
cleanup_message.o: ../../include/been_here.h
cleanup_message.o: ../../include/mail_stream.h
cleanup_message.o: ../../include/mail_conf.h
+cleanup_message.o: ../../include/string_list.h
+cleanup_message.o: ../../include/match_list.h
+cleanup_message.o: ../../include/match_ops.h
cleanup_out.o: cleanup_out.c
cleanup_out.o: ../../include/sys_defs.h
cleanup_out.o: ../../include/msg.h
cleanup_out.o: ../../include/mail_conf.h
cleanup_out.o: ../../include/mime_state.h
cleanup_out.o: ../../include/header_opts.h
+cleanup_out.o: ../../include/string_list.h
+cleanup_out.o: ../../include/match_list.h
+cleanup_out.o: ../../include/match_ops.h
cleanup_out_recipient.o: cleanup_out_recipient.c
cleanup_out_recipient.o: ../../include/sys_defs.h
cleanup_out_recipient.o: ../../include/argv.h
cleanup_out_recipient.o: ../../include/mail_conf.h
cleanup_out_recipient.o: ../../include/mime_state.h
cleanup_out_recipient.o: ../../include/header_opts.h
+cleanup_out_recipient.o: ../../include/string_list.h
+cleanup_out_recipient.o: ../../include/match_list.h
+cleanup_out_recipient.o: ../../include/match_ops.h
cleanup_rewrite.o: cleanup_rewrite.c
cleanup_rewrite.o: ../../include/sys_defs.h
cleanup_rewrite.o: ../../include/msg.h
cleanup_rewrite.o: ../../include/mail_conf.h
cleanup_rewrite.o: ../../include/mime_state.h
cleanup_rewrite.o: ../../include/header_opts.h
+cleanup_rewrite.o: ../../include/string_list.h
+cleanup_rewrite.o: ../../include/match_list.h
+cleanup_rewrite.o: ../../include/match_ops.h
cleanup_state.o: cleanup_state.c
cleanup_state.o: ../../include/sys_defs.h
cleanup_state.o: ../../include/mymalloc.h
cleanup_state.o: ../../include/resolve_clnt.h
cleanup_state.o: ../../include/mail_stream.h
cleanup_state.o: ../../include/mail_conf.h
+cleanup_state.o: ../../include/string_list.h
+cleanup_state.o: ../../include/match_list.h
+cleanup_state.o: ../../include/match_ops.h
#include <mail_stream.h>
#include <mail_conf.h>
#include <mime_state.h>
+#include <string_list.h>
/*
* These state variables are accessed by many functions, and there is only
extern MAPS *cleanup_body_checks;
extern MAPS *cleanup_virt_alias_maps;
extern ARGV *cleanup_masq_domains;
+extern STRING_LIST *cleanup_masq_exceptions;
extern int cleanup_masq_flags;
/*
MAPS *cleanup_body_checks;
MAPS *cleanup_virt_alias_maps;
ARGV *cleanup_masq_domains;
+STRING_LIST *cleanup_masq_exceptions;
int cleanup_masq_flags;
/*
if (*var_body_checks)
cleanup_body_checks =
maps_create(VAR_BODY_CHECKS, var_body_checks, DICT_FLAG_LOCK);
+ if (*var_masq_exceptions)
+ cleanup_masq_exceptions =
+ string_list_init(MATCH_FLAG_NONE, var_masq_exceptions);
if (*var_masq_classes)
cleanup_masq_flags = name_mask(VAR_MASQ_CLASSES, masq_class_table,
var_masq_classes);
int truncate;
/* Stuff for excluded names. */
- static HTABLE *masq_except_table = 0;
- char *saved_names;
char *name;
- char *ptr;
int excluded;
- /*
- * First time, build a lookup table for excluded names.
- */
- if (*var_masq_exceptions && masq_except_table == 0) {
- masq_except_table = htable_create(5);
- ptr = saved_names = mystrdup(var_masq_exceptions);
- while ((name = mystrtok(&ptr, ", \t\r\n")) != 0)
- htable_enter(masq_except_table, lowercase(name), (char *) 0);
- myfree(saved_names);
- }
-
/*
* Find the domain part.
*/
/*
* Don't masquerade excluded names (regardless of domain).
*/
- if (masq_except_table) {
+ if (*var_masq_exceptions) {
name = mystrndup(STR(addr), domain - 1 - STR(addr));
- excluded = (htable_locate(masq_except_table, lowercase(name)) != 0);
+ excluded = (string_list_match(cleanup_masq_exceptions, lowercase(name)) != 0);
myfree(name);
if (excluded)
return;
#include <vstream.h>
char *var_masq_exceptions;
+STRING_LIST *cleanup_masq_exceptions;
int main(int argc, char **argv)
{
msg_fatal("usage: %s exceptions masquerade_list address", argv[0]);
var_masq_exceptions = argv[1];
+ cleanup_masq_exceptions =
+ string_list_init(MATCH_FLAG_NONE, var_masq_exceptions);
masq_domains = argv_split(argv[2], " ,\t\r\n");
addr = vstring_alloc(1);
if (strchr(argv[3], '@') == 0)
char **cpp;
/*
- * Apply the duplicate recipient filter before virtual expansion, so that
- * we can distinguish between different addresses that map onto the same
- * mailbox. The recipient will use our original recipient message header
- * to figure things out.
+ * Distinguish between different original recipient addresses that map
+ * onto the same mailbox. The recipient will use our original recipient
+ * message header to figure things out.
*/
- if (been_here_fixed(state->dups, recip) != 0)
- return;
-
if (cleanup_virt_alias_maps == 0) {
- cleanup_out_string(state, REC_TYPE_ORCP, orcpt);
- cleanup_out_string(state, REC_TYPE_RCPT, recip);
- state->rcpt_count++;
+ if (been_here(state->dups, "%s\n%s", orcpt, recip) == 0) {
+ cleanup_out_string(state, REC_TYPE_ORCP, orcpt);
+ cleanup_out_string(state, REC_TYPE_RCPT, recip);
+ state->rcpt_count++;
+ }
} else {
argv = cleanup_map1n_internal(state, recip, cleanup_virt_alias_maps,
cleanup_ext_prop_mask & EXT_PROP_VIRTUAL);
for (cpp = argv->argv; *cpp; cpp++) {
- cleanup_out_string(state, REC_TYPE_ORCP, orcpt);
- cleanup_out_string(state, REC_TYPE_RCPT, *cpp);
- state->rcpt_count++;
+ if (been_here(state->dups, "%s\n%s", orcpt, *cpp) == 0) {
+ cleanup_out_string(state, REC_TYPE_ORCP, orcpt);
+ cleanup_out_string(state, REC_TYPE_RCPT, *cpp);
+ state->rcpt_count++;
+ }
}
argv_free(argv);
}
pipe_command.o: ../../include/iostuff.h
pipe_command.o: ../../include/timed_wait.h
pipe_command.o: ../../include/set_ugid.h
+pipe_command.o: ../../include/set_eugid.h
pipe_command.o: ../../include/argv.h
pipe_command.o: mail_params.h
pipe_command.o: mail_copy.h
resolve_local.o: own_inet_addr.h
resolve_local.o: resolve_local.h
resolve_local.o: match_parent_style.h
-resover.o: resover.c
-resover.o: ../../include/sys_defs.h
-resover.o: ../../include/msg.h
-resover.o: ../../include/vstring.h
-resover.o: ../../include/vbuf.h
-resover.o: ../../include/split_at.h
rewrite_clnt.o: rewrite_clnt.c
rewrite_clnt.o: ../../include/sys_defs.h
rewrite_clnt.o: ../../include/msg.h
{
const char *cp;
- for (cp = defval; /* void */ ; cp++) {
+ for (cp = mail_conf_eval(defval); /* void */ ; cp++) {
if (*cp == 0)
msg_panic("parameter %s: missing time unit in default value: %s",
name, defval);
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
-#define MAIL_RELEASE_DATE "20030126"
+#define MAIL_RELEASE_DATE "20030219"
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "2.0.3-" MAIL_RELEASE_DATE
+#define DEF_MAIL_VERSION "2.0.4-" MAIL_RELEASE_DATE
extern char *var_mail_version;
/*
#include <iostuff.h>
#include <timed_wait.h>
#include <set_ugid.h>
+#include <set_eugid.h>
#include <argv.h>
/* Global library. */
}
}
+/* kill_command - terminate command forcibly */
+
+static void kill_command(pid_t pid, int sig, uid_t kill_uid, gid_t kill_gid)
+{
+ pid_t saved_euid = geteuid();
+ gid_t saved_egid = getegid();
+
+ /*
+ * Switch privileges to that of the child process. Terminate the child
+ * and its offspring.
+ */
+ set_eugid(kill_uid, kill_gid);
+ if (kill(-pid, sig) < 0 && kill(pid, sig) < 0)
+ msg_warn("cannot kill process (group) %lu: %m",
+ (unsigned long) pid);
+ set_eugid(saved_euid, saved_egid);
+}
+
/* pipe_command_wait_or_kill - wait for command with time limit, or kill it */
-static int pipe_command_wait_or_kill(pid_t pid, WAIT_STATUS_T *statusp, int sig)
+static int pipe_command_wait_or_kill(pid_t pid, WAIT_STATUS_T *statusp, int sig,
+ uid_t kill_uid, gid_t kill_gid)
{
int maxtime = (pipe_command_timeout == 0) ? pipe_command_maxtime : 1;
char *myname = "pipe_command_wait_or_kill";
msg_info("%s: time limit exceeded", myname);
pipe_command_timeout = 1;
}
- kill(-pid, sig);
+ kill_command(pid, sig, kill_uid, kill_gid);
n = waitpid(pid, statusp, 0);
}
return (n);
* truncated without too much loss. I could even argue that truncating
* the amount of diagnostic output is a good thing to do, but I won't go
* that far.
+ *
+ * Turn on non-blocking writes to the child process so that we can enforce
+ * timeouts after partial writes.
*/
if (pipe(cmd_in_pipe) < 0 || pipe(cmd_out_pipe) < 0)
msg_fatal("%s: pipe: %m", myname);
non_blocking(cmd_out_pipe[1], NON_BLOCKING);
+ non_blocking(cmd_in_pipe[1], NON_BLOCKING);
/*
* Spawn off a child process and irrevocably change privilege to the
* not just the child process but also its offspring.
*/
if (pipe_command_timeout)
- (void) kill(-pid, SIGKILL);
- if (pipe_command_wait_or_kill(pid, &wait_status, SIGKILL) < 0)
+ kill_command(pid, SIGKILL, args.uid, args.gid);
+ if (pipe_command_wait_or_kill(pid, &wait_status, SIGKILL,
+ args.uid, args.gid) < 0)
msg_fatal("wait: %m");
if (pipe_command_timeout) {
vstring_sprintf(why, "Command time limit exceeded: \"%s\"%s%s",
* this is "postfix internal" information. However, the pickup server has to
* allow for the presence of A records in the extracted segment, because it
* can be requested to re-process already queued mail with `postsuper -r'.
+ *
+ * Note: REC_TYPE_FILT and REC_TYPE_CONT are encoded with the same 'L'
+ * constant, and it is too late to change that now.
*/
#define REC_TYPE_ENVELOPE "MCTFILSDROWVA>"
#define REC_TYPE_CONTENT "XLN"
-#define REC_TYPE_EXTRACT "EDROPreAFI>"
+#define REC_TYPE_EXTRACT "EDROPreAFIL>"
/*
* The record at the beginning of the envelope segment specifies the message
*
* [...]
*
- * # Pn, where n is (in decimal) the process ID.
+ * Pn, where n is (in decimal) the process ID.
*
* [...]
*/
if (type == REC_TYPE_INSP)
/* Use current content inspection settings instead. */
continue;
- if (type == REC_TYPE_FILT)
+
+ /*
+ * XXX Workaround: REC_TYPE_FILT (used in envelopes) == REC_TYPE_CONT
+ * (used in message content).
+ */
+ if (type == REC_TYPE_FILT && *expected != REC_TYPE_CONTENT[0])
/* Use current content filter settings instead. */
continue;
else {
"", " ", "",
&state->sasl_mechanism_list,
IGNORE_MECHANISM_LEN,
- &sasl_mechanism_count) != SASL_OK
- || sasl_mechanism_count <= 0)
+ &sasl_mechanism_count) != SASL_OK)
+ msg_fatal("cannot lookup SASL authentication mechanisms");
+ if (sasl_mechanism_count <= 0)
msg_fatal("no SASL authentication mechanisms");
}
*
* [...]
*
- * # Pn, where n is (in decimal) the process ID.
+ * Pn, where n is (in decimal) the process ID.
*
* [...]
*/