From: Wietse Venema
Uncomment the new "smtpd pass ... smtpd" service in master.cf, and duplicate any "-o parameter=value" entries -from the smtpd service that was commented out in step 1.
+from the smtpd service that was commented out in the previous step. +/etc/postfix/master.cf: diff --git a/postfix/proto/POSTSCREEN_README.html b/postfix/proto/POSTSCREEN_README.html index de4640099..e71ebe1a9 100644 --- a/postfix/proto/POSTSCREEN_README.html +++ b/postfix/proto/POSTSCREEN_README.html @@ -701,7 +701,8 @@ that follow.
Uncomment the new "smtpd pass ... smtpd" service in master.cf, and duplicate any "-o parameter=value" entries -from the smtpd service that was commented out in step 1.
+from the smtpd service that was commented out in the previous step. +
/etc/postfix/master.cf:
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index e4ceb0dc5..77e8821a0 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 "20110120"
+#define MAIL_RELEASE_DATE "20110124"
#define MAIL_VERSION_NUMBER "2.9"
#ifdef SNAPSHOT
diff --git a/postfix/src/global/smtp_stream.c b/postfix/src/global/smtp_stream.c
index 82d18e513..73ad87054 100644
--- a/postfix/src/global/smtp_stream.c
+++ b/postfix/src/global/smtp_stream.c
@@ -52,7 +52,7 @@
/* and write operations described below.
/* This routine alters the behavior of streams as follows:
/* .IP \(bu
-/* The read/write timeout is set to the specified value.
+/* The read/write total time limit is set to the specified value.
/* .IP \f(bu
/* The stream is configured to use double buffering.
/* .IP \f(bu
@@ -151,6 +151,16 @@
static void smtp_timeout_reset(VSTREAM *stream)
{
vstream_clearerr(stream);
+
+ /*
+ * Important: the time limit feature must not introduce any system calls
+ * when the input is already in the buffer, or when the output still fits
+ * in the buffer. Such system calls would really hurt when receiving or
+ * sending body content one line at a time.
+ */
+ vstream_control(stream,
+ VSTREAM_CTL_TIME_LIMIT, stream->timeout,
+ VSTREAM_CTL_END);
}
/* smtp_timeout_detect - test the per-stream timeout flag */
diff --git a/postfix/src/postscreen/postscreen.c b/postfix/src/postscreen/postscreen.c
index 7b3332b61..67bfe3caa 100644
--- a/postfix/src/postscreen/postscreen.c
+++ b/postfix/src/postscreen/postscreen.c
@@ -416,13 +416,6 @@ int var_psc_post_queue_limit;
int var_psc_pre_queue_limit;
int var_psc_watchdog;
-#undef MIGRATION_WARNING
-
-#ifdef MIGRATION_WARNING
-char *var_psc_wlist_nets;
-char *var_psc_blist_nets;
-
-#endif
char *var_psc_acl;
char *var_psc_blist_action;
@@ -495,11 +488,6 @@ HTABLE *psc_client_concurrency; /* per-client concurrency */
/*
* Local variables.
*/
-#ifdef MIGRATION_WARNING
-static ADDR_MATCH_LIST *psc_wlist_nets; /* permanently whitelisted networks */
-static ADDR_MATCH_LIST *psc_blist_nets; /* permanently blacklisted networks */
-
-#endif
static ARGV *psc_acl; /* permanent white/backlist */
static int psc_blist_action; /* PSC_ACT_DROP/ENFORCE/etc */
@@ -715,47 +703,6 @@ static void psc_service(VSTREAM *smtp_client_stream,
break;
}
}
-#ifdef MIGRATION_WARNING
-
- /*
- * The permanent whitelist has highest precedence (never block mail from
- * whitelisted sites, and never run tests against those sites).
- */
- if (psc_wlist_nets != 0
- && psc_addr_match_list_match(psc_wlist_nets, state->smtp_client_addr)) {
- msg_info("WHITELISTED [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
- psc_conclude(state);
- return;
- }
-
- /*
- * The permanent blacklist has second precedence. If the client is
- * permanently blacklisted, send some generic reply and hang up
- * immediately, or run more tests for logging purposes.
- */
- if (psc_blist_nets != 0
- && psc_addr_match_list_match(psc_blist_nets, state->smtp_client_addr)) {
- msg_info("BLACKLISTED [%s]:%s", PSC_CLIENT_ADDR_PORT(state));
- PSC_FAIL_SESSION_STATE(state, PSC_STATE_FLAG_BLIST_FAIL);
- switch (psc_blist_action) {
- case PSC_ACT_DROP:
- PSC_DROP_SESSION_STATE(state,
- "521 5.3.2 Service currently unavailable\r\n");
- return;
- case PSC_ACT_ENFORCE:
- PSC_ENFORCE_SESSION_STATE(state,
- "550 5.3.2 Service currently unavailable\r\n");
- break;
- case PSC_ACT_IGNORE:
- PSC_UNFAIL_SESSION_STATE(state, PSC_STATE_FLAG_BLIST_FAIL);
- /* Not: PSC_PASS_SESSION_STATE. Repeat this test the next time. */
- break;
- default:
- msg_panic("%s: unknown blacklist action value %d",
- myname, psc_blist_action);
- }
- }
-#endif
/*
* The temporary whitelist (i.e. the postscreen cache) has the lowest
@@ -787,7 +734,8 @@ static void psc_service(VSTREAM *smtp_client_stream,
}
/*
- * Reply with 421 when we can't analyze more connections.
+ * Reply with 421 when we can't analyze more connections. That also means
+ * no deep protocol tests when the noforward flag is raised.
*/
if (var_psc_pre_queue_limit > 0
&& psc_check_queue_length - psc_post_queue_length
@@ -841,21 +789,6 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
* Open read-only maps before dropping privilege, for consistency with
* other Postfix daemons.
*/
-#ifdef MIGRATION_WARNING
- if (*var_psc_wlist_nets)
- psc_wlist_nets =
- addr_match_list_init(MATCH_FLAG_NONE, var_psc_wlist_nets);
-
- if (*var_psc_blist_nets)
- psc_blist_nets = addr_match_list_init(MATCH_FLAG_NONE,
- var_psc_blist_nets);
- if (psc_blist_nets || psc_wlist_nets) {
- msg_warn("The %s and %s features will be removed soon. Use %s instead",
- VAR_PSC_WLIST_NETS, VAR_PSC_BLIST_NETS, VAR_PSC_ACL);
- msg_warn("To stop this warning, specify empty values for %s and %s",
- VAR_PSC_WLIST_NETS, VAR_PSC_BLIST_NETS);
- }
-#endif
psc_acl_pre_jail_init();
if (*var_psc_acl)
psc_acl = psc_acl_parse(var_psc_acl, VAR_PSC_ACL);
@@ -1095,10 +1028,6 @@ int main(int argc, char **argv)
VAR_PSC_PIPEL_ACTION, DEF_PSC_PIPEL_ACTION, &var_psc_pipel_action, 1, 0,
VAR_PSC_NSMTP_ACTION, DEF_PSC_NSMTP_ACTION, &var_psc_nsmtp_action, 1, 0,
VAR_PSC_BARLF_ACTION, DEF_PSC_BARLF_ACTION, &var_psc_barlf_action, 1, 0,
-#ifdef MIGRATION_WARNING
- VAR_PSC_WLIST_NETS, DEF_PSC_WLIST_NETS, &var_psc_wlist_nets, 0, 0,
- VAR_PSC_BLIST_NETS, DEF_PSC_BLIST_NETS, &var_psc_blist_nets, 0, 0,
-#endif
VAR_PSC_ACL, DEF_PSC_ACL, &var_psc_acl, 0, 0,
VAR_PSC_BLIST_ACTION, DEF_PSC_BLIST_ACTION, &var_psc_blist_action, 1, 0,
VAR_PSC_FORBID_CMDS, DEF_PSC_FORBID_CMDS, &var_psc_forbid_cmds, 0, 0,
diff --git a/postfix/src/util/vstream.c b/postfix/src/util/vstream.c
index ba3e842b1..9ee143a81 100644
--- a/postfix/src/util/vstream.c
+++ b/postfix/src/util/vstream.c
@@ -304,6 +304,12 @@
/* int. Use an explicit cast to avoid problems on LP64
/* environments and other environments where ssize_t is larger
/* than int.
+/* .IP "VSTREAM_CTL_TIME_LIMIT (int)"
+/* Specify an upper bound on the total time to complete all
+/* subsequent read or write operations. This is different from
+/* VSTREAM_CTL_TIMEOUT, which specifies a deadline for each
+/* read or write operation. Specify a relative time in seconds,
+/* or zero to disable this feature.
/* .PP
/* vstream_fileno() gives access to the file handle associated with
/* a buffered stream. With streams that have separate read/write
@@ -522,6 +528,21 @@ VSTREAM vstream_fstd[] = {
#define VSTREAM_FFLUSH_SOME(stream) \
vstream_fflush_some((stream), (stream)->buf.len - (stream)->buf.cnt)
+/* Note: this does not change a negative result into a zero result. */
+#define VSTREAM_SUB_TIME(x, y, z) \
+ do { \
+ (x).tv_sec = (y).tv_sec - (z).tv_sec; \
+ (x).tv_usec = (y).tv_usec - (z).tv_usec; \
+ while ((x).tv_usec < 0) { \
+ (x).tv_usec += 1000000; \
+ (x).tv_sec -= 1; \
+ } \
+ while ((x).tv_usec >= 1000000) { \
+ (x).tv_usec -= 1000000; \
+ (x).tv_sec += 1; \
+ } \
+ } while (0)
+
/* vstream_buf_init - initialize buffer */
static void vstream_buf_init(VBUF *bp, int flags)
@@ -590,6 +611,9 @@ static int vstream_fflush_some(VSTREAM *stream, ssize_t to_flush)
char *data;
ssize_t len;
ssize_t n;
+ int timeout;
+ struct timeval before;
+ struct timeval elapsed;
/*
* Sanity checks. It is illegal to flush a read-only stream. Otherwise,
@@ -630,14 +654,31 @@ static int vstream_fflush_some(VSTREAM *stream, ssize_t to_flush)
* any.
*/
for (data = (char *) bp->data, len = to_flush; len > 0; len -= n, data += n) {
- if ((n = stream->write_fn(stream->fd, data, len, stream->timeout, stream->context)) <= 0) {
+ if (bp->flags & VSTREAM_FLAG_DEADLINE) {
+ timeout = stream->time_limit.tv_sec + (stream->time_limit.tv_usec > 0);
+ if (timeout <= 0) {
+ bp->flags |= (VSTREAM_FLAG_ERR | VSTREAM_FLAG_TIMEOUT);
+ errno = ETIMEDOUT;
+ return (VSTREAM_EOF);
+ }
+ if (len == to_flush)
+ GETTIMEOFDAY(&before);
+ else
+ before = stream->iotime;
+ } else
+ timeout = stream->timeout;
+ if ((n = stream->write_fn(stream->fd, data, len, timeout, stream->context)) <= 0) {
bp->flags |= VSTREAM_FLAG_ERR;
if (errno == ETIMEDOUT)
bp->flags |= VSTREAM_FLAG_TIMEOUT;
return (VSTREAM_EOF);
}
- if (stream->timeout)
+ if (timeout)
GETTIMEOFDAY(&stream->iotime);
+ if (bp->flags & VSTREAM_FLAG_DEADLINE) {
+ VSTREAM_SUB_TIME(elapsed, stream->iotime, before);
+ VSTREAM_SUB_TIME(stream->time_limit, stream->time_limit, elapsed);
+ }
if (msg_verbose > 2 && stream != VSTREAM_ERR && n != to_flush)
msg_info("%s: %d flushed %ld/%ld", myname, stream->fd,
(long) n, (long) to_flush);
@@ -698,6 +739,9 @@ static int vstream_buf_get_ready(VBUF *bp)
VSTREAM *stream = VBUF_TO_APPL(bp, VSTREAM, buf);
const char *myname = "vstream_buf_get_ready";
ssize_t n;
+ struct timeval before;
+ struct timeval elapsed;
+ int timeout;
/*
* Detect a change of I/O direction or position. If so, flush any
@@ -759,7 +803,17 @@ static int vstream_buf_get_ready(VBUF *bp)
* data as is available right now, whichever is less. Update the cached
* file seek position, if any.
*/
- switch (n = stream->read_fn(stream->fd, bp->data, bp->len, stream->timeout, stream->context)) {
+ if (bp->flags & VSTREAM_FLAG_DEADLINE) {
+ timeout = stream->time_limit.tv_sec + (stream->time_limit.tv_usec > 0);
+ if (timeout <= 0) {
+ bp->flags |= (VSTREAM_FLAG_ERR | VSTREAM_FLAG_TIMEOUT);
+ errno = ETIMEDOUT;
+ return (VSTREAM_EOF);
+ }
+ GETTIMEOFDAY(&before);
+ } else
+ timeout = stream->timeout;
+ switch (n = stream->read_fn(stream->fd, bp->data, bp->len, timeout, stream->context)) {
case -1:
bp->flags |= VSTREAM_FLAG_ERR;
if (errno == ETIMEDOUT)
@@ -769,8 +823,12 @@ static int vstream_buf_get_ready(VBUF *bp)
bp->flags |= VSTREAM_FLAG_EOF;
return (VSTREAM_EOF);
default:
- if (stream->timeout)
+ if (timeout)
GETTIMEOFDAY(&stream->iotime);
+ if (bp->flags & VSTREAM_FLAG_DEADLINE) {
+ VSTREAM_SUB_TIME(elapsed, stream->iotime, before);
+ VSTREAM_SUB_TIME(stream->time_limit, stream->time_limit, elapsed);
+ }
if (msg_verbose > 2)
msg_info("%s: fd %d got %ld", myname, stream->fd, (long) n);
bp->cnt = -n;
@@ -1082,6 +1140,7 @@ VSTREAM *vstream_fdopen(int fd, int flags)
stream->context = 0;
stream->jbuf = 0;
stream->iotime.tv_sec = stream->iotime.tv_usec = 0;
+ stream->time_limit.tv_sec = stream->time_limit.tv_usec = 0;
stream->req_bufsize = VSTREAM_BUFSIZE;
return (stream);
}
@@ -1227,6 +1286,7 @@ void vstream_control(VSTREAM *stream, int name,...)
int old_fd;
ssize_t req_bufsize = 0;
VSTREAM *stream2;
+ int time_limit;
#define SWAP(type,a,b) do { type temp = (a); (a) = (b); (b) = (temp); } while (0)
@@ -1334,6 +1394,24 @@ void vstream_control(VSTREAM *stream, int name,...)
&& req_bufsize > stream->req_bufsize)
stream->req_bufsize = req_bufsize;
break;
+
+ /*
+ * Make no gettimeofday() etc. system call until we really know
+ * that we need to do I/O. This avoids a performance hit when
+ * sending or receiving body content one line at a time.
+ */
+ case VSTREAM_CTL_TIME_LIMIT:
+ time_limit = va_arg(ap, int);
+ if (time_limit < 0) {
+ msg_panic("%s: bad time limit: %d", myname, time_limit);
+ } else if (time_limit == 0) {
+ stream->buf.flags &= ~VSTREAM_FLAG_DEADLINE;
+ } else {
+ stream->buf.flags |= VSTREAM_FLAG_DEADLINE;
+ stream->time_limit.tv_sec = time_limit;
+ stream->time_limit.tv_usec = 0;
+ }
+ break;
default:
msg_panic("%s: bad name %d", myname, name);
}
diff --git a/postfix/src/util/vstream.h b/postfix/src/util/vstream.h
index 3c6c16aea..fb7d05854 100644
--- a/postfix/src/util/vstream.h
+++ b/postfix/src/util/vstream.h
@@ -57,6 +57,7 @@ typedef struct VSTREAM {
int timeout; /* read/write timout */
VSTREAM_JMP_BUF *jbuf; /* exception handling */
struct timeval iotime; /* time of last fill/flush */
+ struct timeval time_limit; /* read/write time limit */
} VSTREAM;
extern VSTREAM vstream_fstd[]; /* pre-defined streams */
@@ -76,6 +77,7 @@ extern VSTREAM vstream_fstd[]; /* pre-defined streams */
#define VSTREAM_FLAG_SEEK (1<<10) /* seek info valid */
#define VSTREAM_FLAG_NSEEK (1<<11) /* can't seek this file */
#define VSTREAM_FLAG_DOUBLE (1<<12) /* double buffer */
+#define VSTREAM_FLAG_DEADLINE (1<<13) /* deadline active */
#define VSTREAM_PURGE_READ (1<<0) /* flush unread data */
#define VSTREAM_PURGE_WRITE (1<<1) /* flush unwritten data */
@@ -133,6 +135,7 @@ extern void vstream_control(VSTREAM *, int,...);
#endif
#define VSTREAM_CTL_BUFSIZE 12
#define VSTREAM_CTL_SWAP_FD 13
+#define VSTREAM_CTL_TIME_LIMIT 14
extern VSTREAM *PRINTFLIKE(1, 2) vstream_printf(const char *,...);
extern VSTREAM *PRINTFLIKE(2, 3) vstream_fprintf(VSTREAM *, const char *,...);