mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 05:38:06 +00:00
postfix-2.3-20060403
This commit is contained in:
parent
303c7c57dd
commit
ee4ef8eeb6
@ -12064,6 +12064,34 @@ Apologies for any names omitted.
|
||||
test. A filter timeout was mis-reported as lost connection.
|
||||
Found in code review. File: smtpd/smtpd_proxy.c.
|
||||
|
||||
20060327
|
||||
|
||||
Cleanup: the SQL and LDAP clients now log a warning when
|
||||
they skip an empty lookup result, so that humans don't have
|
||||
to wonder why Postfix doesn't find all the database entries.
|
||||
File: global/db_common.c.
|
||||
|
||||
20060328
|
||||
|
||||
Feature: configurable chroot directive for the pipe(8)
|
||||
delivery agent, by Przemyslaw Wegrzyn. Files:
|
||||
global/pipe_command.c, pipe/pipe.c.
|
||||
|
||||
Bugfix: cut-and-paste error: lmtp_connection_cache_limit
|
||||
was left with the name of smtp_connection_cache_limit.
|
||||
Reported by Victor? File: src/global/mail_params.h.
|
||||
|
||||
20060403
|
||||
|
||||
Cleanup: made fcntl/flock handling consistent with respect
|
||||
to EINTR (reported by Carlo Contavalli). However, Postfix
|
||||
is not meant to be signal safe. Only the master daemon
|
||||
handles signals without terminating, and it uses only a
|
||||
small subset of Postfix library routines. File: util/myflock.c.
|
||||
|
||||
Bugfix: the pipe-to-command error message was lost when the
|
||||
command could not be executed. File: global/pipe_command.c.
|
||||
|
||||
Wish list:
|
||||
|
||||
Don't send xforward attributes to every site that announces
|
||||
|
@ -181,11 +181,17 @@ that the Postfix queue is under /var/spool/postfix/.
|
||||
|
||||
/some/where/dovecot.conf:
|
||||
auth default {
|
||||
..
|
||||
mechanisms = plain login
|
||||
passdb pam {
|
||||
}
|
||||
userdb passwd {
|
||||
}
|
||||
socket listen {
|
||||
client {
|
||||
path = /var/spool/postfix/private/auth
|
||||
mode = 0666
|
||||
mode = 0660
|
||||
user = postfix
|
||||
group = postfix
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -447,7 +453,7 @@ CCrreeddiittss
|
||||
reject_authenticated_sender_login_mismatch and
|
||||
reject_unauthenticated_sender_login_mismatch, and revised the docs.
|
||||
* Wietse made another iteration through the code to add plug-in support for
|
||||
multiple implementations.
|
||||
* The Dovecot SMTP server plug-in was originally implemented by Timo Sirainen
|
||||
of Procontrol, Finland.
|
||||
multiple SASL implementations.
|
||||
* The Dovecot SMTP server-only plug-in was originally implemented by Timo
|
||||
Sirainen of Procontrol, Finland.
|
||||
|
||||
|
@ -140,7 +140,7 @@ in the Postfix top-level directory: </p>
|
||||
|
||||
<li> <p> The "-DDEF_SASL_SERVER" stuff is not necessary; it just
|
||||
makes Postfix configuration a little more convenient because you
|
||||
don't have to specify the SASL plug-in type in the Postfix main.cf
|
||||
don't have to specify the SASL plug-in type in the Postfix <a href="postconf.5.html">main.cf</a>
|
||||
file. </p>
|
||||
|
||||
<li> <p> If you also want support for LDAP or TLS, you will have to merge
|
||||
@ -229,7 +229,7 @@ SMTP server</a></h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#smtpd_sasl_auth_enable">smtpd_sasl_auth_enable</a> = yes
|
||||
</pre>
|
||||
</blockquote>
|
||||
@ -238,7 +238,7 @@ SMTP server</a></h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
|
||||
<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a> <a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a> ...
|
||||
</pre>
|
||||
@ -249,7 +249,7 @@ SMTP server</a></h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#smtpd_sasl_authenticated_header">smtpd_sasl_authenticated_header</a> = yes
|
||||
</pre>
|
||||
</blockquote>
|
||||
@ -265,7 +265,7 @@ clients) use the following: </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#broken_sasl_auth_clients">broken_sasl_auth_clients</a> = yes
|
||||
</pre>
|
||||
</blockquote>
|
||||
@ -281,7 +281,7 @@ Postfix runs chrooted: </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#smtpd_sasl_type">smtpd_sasl_type</a> = dovecot
|
||||
<a href="postconf.5.html#smtpd_sasl_path">smtpd_sasl_path</a> = private/auth
|
||||
</pre>
|
||||
@ -296,11 +296,17 @@ Postfix queue is under /var/spool/postfix/. </p>
|
||||
<pre>
|
||||
/some/where/dovecot.conf:
|
||||
auth default {
|
||||
..
|
||||
mechanisms = plain login
|
||||
passdb pam {
|
||||
}
|
||||
userdb passwd {
|
||||
}
|
||||
socket listen {
|
||||
client {
|
||||
path = /var/spool/postfix/private/auth
|
||||
mode = 0666
|
||||
mode = 0660
|
||||
user = postfix
|
||||
group = postfix
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -352,7 +358,7 @@ library for configuration can be set with: </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
smtpd_sasl_application_name = smtpd
|
||||
</pre>
|
||||
</blockquote>
|
||||
@ -449,7 +455,7 @@ realm used by smtpd: </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#smtpd_sasl_local_domain">smtpd_sasl_local_domain</a> = $<a href="postconf.5.html#myhostname">myhostname</a>
|
||||
</pre>
|
||||
</blockquote>
|
||||
@ -593,7 +599,7 @@ table. </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#smtp_sasl_auth_enable">smtp_sasl_auth_enable</a> = yes
|
||||
<a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> = hash:/etc/postfix/sasl_passwd
|
||||
<a href="postconf.5.html#smtp_sasl_type">smtp_sasl_type</a> = cyrus
|
||||
@ -612,7 +618,7 @@ before it searches by destination, specify: </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#smtp_sender_dependent_authentication">smtp_sender_dependent_authentication</a> = yes
|
||||
<a href="postconf.5.html#smtp_sasl_auth_enable">smtp_sasl_auth_enable</a> = yes
|
||||
<a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> = hash:/etc/postfix/sasl_passwd
|
||||
@ -634,7 +640,7 @@ for example: </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#smtp_sasl_security_options">smtp_sasl_security_options</a> = noanonymous
|
||||
</pre>
|
||||
</blockquote>
|
||||
@ -652,7 +658,7 @@ into consideration: </p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
/etc/postfix/main.cf:
|
||||
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
|
||||
<a href="postconf.5.html#smtp_sasl_mechanism_filter">smtp_sasl_mechanism_filter</a> = !gssapi, !external, static:all
|
||||
</pre>
|
||||
</blockquote>
|
||||
@ -682,9 +688,9 @@ of SuSE Rhein/Main AG.
|
||||
<a href="postconf.5.html#reject_unauthenticated_sender_login_mismatch">reject_unauthenticated_sender_login_mismatch</a>, and revised the docs.
|
||||
|
||||
<li> Wietse made another iteration through the code to add
|
||||
plug-in support for multiple implementations.
|
||||
plug-in support for multiple SASL implementations.
|
||||
|
||||
<li> The Dovecot SMTP server plug-in was originally implemented by
|
||||
<li> The Dovecot SMTP server-only plug-in was originally implemented by
|
||||
Timo Sirainen of Procontrol, Finland.
|
||||
|
||||
</ul>
|
||||
|
@ -48,9 +48,22 @@ PIPE(8) PIPE(8)
|
||||
file at the end of a service definition. The syntax is as
|
||||
follows:
|
||||
|
||||
<b>directory=</b><i>pathname</i> (optional, default: <b>$<a href="postconf.5.html#queue_directory">queue_directory</a></b>)
|
||||
Change to the named directory before executing the
|
||||
external command. Delivery is deferred in case of
|
||||
<b>chroot=</b><i>pathname</i> (optional)
|
||||
Change the process root directory and working
|
||||
directory to the named directory. This happens
|
||||
before switching to the privileges specified with
|
||||
the <b>user</b> attribute, and before executing the
|
||||
optional <b>directory=</b><i>pathname</i> directive. Delivery is
|
||||
deferred in case of failure.
|
||||
|
||||
This feature is available as of Postfix 2.3.
|
||||
|
||||
<b>directory=</b><i>pathname</i> (optional)
|
||||
Change to the named directory before executing the
|
||||
external command. The directory must be accessible
|
||||
for the user specified with the <b>user</b> attribute (see
|
||||
below). The default working directory is
|
||||
<b>$<a href="postconf.5.html#queue_directory">queue_directory</a></b>. Delivery is deferred in case of
|
||||
failure.
|
||||
|
||||
This feature is available as of Postfix 2.2.
|
||||
@ -162,9 +175,9 @@ PIPE(8) PIPE(8)
|
||||
<b>user</b>=<i>username</i> (required)
|
||||
|
||||
<b>user</b>=<i>username</i>:<i>groupname</i>
|
||||
The external command is executed with the rights of
|
||||
the specified <i>username</i>. The software refuses to
|
||||
execute commands with root privileges, or with the
|
||||
Execute the external command with the rights of the
|
||||
specified <i>username</i>. The software refuses to exe-
|
||||
cute commands with root privileges, or with the
|
||||
privileges of the mail system owner. If <i>groupname</i>
|
||||
is specified, the corresponding group ID is used
|
||||
instead of the group ID of <i>username</i>.
|
||||
|
@ -3154,6 +3154,18 @@ configuration parameter. See there for details. </p>
|
||||
<p> This feature is available in Postfix 2.3 and later. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="lmtp_connection_cache_time_limit">lmtp_connection_cache_time_limit</a>
|
||||
(default: 2s)</b></DT><DD>
|
||||
|
||||
<p> The LMTP-specific version of the
|
||||
<a href="postconf.5.html#smtp_connection_cache_time_limit">smtp_connection_cache_time_limit</a> configuration parameter.
|
||||
See there for details. </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.3 and later. </p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="lmtp_connection_reuse_time_limit">lmtp_connection_reuse_time_limit</a>
|
||||
|
@ -1705,6 +1705,12 @@ The LMTP-specific version of the smtp_connection_cache_on_demand
|
||||
configuration parameter. See there for details.
|
||||
.PP
|
||||
This feature is available in Postfix 2.3 and later.
|
||||
.SH lmtp_connection_cache_time_limit (default: 2s)
|
||||
The LMTP-specific version of the
|
||||
smtp_connection_cache_time_limit configuration parameter.
|
||||
See there for details.
|
||||
.PP
|
||||
This feature is available in Postfix 2.3 and later.
|
||||
.SH lmtp_connection_reuse_time_limit (default: 300s)
|
||||
The LMTP-specific version of the smtp_connection_reuse_time_limit
|
||||
configuration parameter. See there for details.
|
||||
|
@ -51,8 +51,19 @@ entry for the pipe-based delivery transport.
|
||||
.fi
|
||||
The external command attributes are given in the \fBmaster.cf\fR
|
||||
file at the end of a service definition. The syntax is as follows:
|
||||
.IP "\fBdirectory=\fIpathname\fR (optional, default: \fB$queue_directory\fR)"
|
||||
.IP "\fBchroot=\fIpathname\fR (optional)"
|
||||
Change the process root directory and working directory to
|
||||
the named directory. This happens before switching to the
|
||||
privileges specified with the \fBuser\fR attribute, and
|
||||
before executing the optional \fBdirectory=\fIpathname\fR
|
||||
directive. Delivery is deferred in case of failure.
|
||||
.sp
|
||||
This feature is available as of Postfix 2.3.
|
||||
.IP "\fBdirectory=\fIpathname\fR (optional)"
|
||||
Change to the named directory before executing the external command.
|
||||
The directory must be accessible for the user specified with the
|
||||
\fBuser\fR attribute (see below).
|
||||
The default working directory is \fB$queue_directory\fR.
|
||||
Delivery is deferred in case of failure.
|
||||
.sp
|
||||
This feature is available as of Postfix 2.2.
|
||||
@ -148,7 +159,7 @@ Messages greater in size than this limit (in bytes) will
|
||||
be returned to the sender as undeliverable.
|
||||
.IP "\fBuser\fR=\fIusername\fR (required)"
|
||||
.IP "\fBuser\fR=\fIusername\fR:\fIgroupname\fR"
|
||||
The external command is executed with the rights of the
|
||||
Execute the external command with the rights of the
|
||||
specified \fIusername\fR. The software refuses to execute
|
||||
commands with root privileges, or with the privileges of the
|
||||
mail system owner. If \fIgroupname\fR is specified, the
|
||||
|
@ -201,6 +201,7 @@ while (<>) {
|
||||
s;\blmtp_sasl_mechanism_filter\b;<a href="postconf.5.html#lmtp_sasl_mechanism_filter">$&</a>;g;
|
||||
s;\blmtp_host_lookup\b;<a href="postconf.5.html#lmtp_host_lookup">$&</a>;g;
|
||||
s;\blmtp_connection_cache_destinations\b;<a href="postconf.5.html#lmtp_connection_cache_destinations">$&</a>;g;
|
||||
s;\blmtp_connection_cache_time_limit\b;<a href="postconf.5.html#lmtp_connection_cache_time_limit">$&</a>;g;
|
||||
s;\blmtp_tls_per_site\b;<a href="postconf.5.html#lmtp_tls_per_site">$&</a>;g;
|
||||
s;\blmtp_generic_maps\b;<a href="postconf.5.html#lmtp_generic_maps">$&</a>;g;
|
||||
s;\blmtp_pix_workaround_threshold_time\b;<a href="postconf.5.html#lmtp_pix_workaround_threshold_time">$&</a>;g;
|
||||
|
@ -296,11 +296,17 @@ Postfix queue is under /var/spool/postfix/. </p>
|
||||
<pre>
|
||||
/some/where/dovecot.conf:
|
||||
auth default {
|
||||
..
|
||||
mechanisms = plain login
|
||||
passdb pam {
|
||||
}
|
||||
userdb passwd {
|
||||
}
|
||||
socket listen {
|
||||
client {
|
||||
path = /var/spool/postfix/private/auth
|
||||
mode = 0666
|
||||
mode = 0660
|
||||
user = postfix
|
||||
group = postfix
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -682,9 +688,9 @@ reject_authenticated_sender_login_mismatch and
|
||||
reject_unauthenticated_sender_login_mismatch, and revised the docs.
|
||||
|
||||
<li> Wietse made another iteration through the code to add
|
||||
plug-in support for multiple implementations.
|
||||
plug-in support for multiple SASL implementations.
|
||||
|
||||
<li> The Dovecot SMTP server plug-in was originally implemented by
|
||||
<li> The Dovecot SMTP server-only plug-in was originally implemented by
|
||||
Timo Sirainen of Procontrol, Finland.
|
||||
|
||||
</ul>
|
||||
|
@ -9243,6 +9243,14 @@ See there for details. </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.3 and later. </p>
|
||||
|
||||
%PARAM lmtp_connection_cache_time_limit 2s
|
||||
|
||||
<p> The LMTP-specific version of the
|
||||
smtp_connection_cache_time_limit configuration parameter.
|
||||
See there for details. </p>
|
||||
|
||||
<p> This feature is available in Postfix 2.3 and later. </p>
|
||||
|
||||
%PARAM smtpd_delay_open_until_valid_rcpt yes
|
||||
|
||||
<p> Postpone the start of an SMTP mail transaction until a valid
|
||||
|
@ -1415,10 +1415,12 @@ own_inet_addr.o: mail_params.h
|
||||
own_inet_addr.o: own_inet_addr.c
|
||||
own_inet_addr.o: own_inet_addr.h
|
||||
pipe_command.o: ../../include/argv.h
|
||||
pipe_command.o: ../../include/chroot_uid.h
|
||||
pipe_command.o: ../../include/clean_env.h
|
||||
pipe_command.o: ../../include/exec_command.h
|
||||
pipe_command.o: ../../include/iostuff.h
|
||||
pipe_command.o: ../../include/msg.h
|
||||
pipe_command.o: ../../include/msg_vstream.h
|
||||
pipe_command.o: ../../include/set_eugid.h
|
||||
pipe_command.o: ../../include/set_ugid.h
|
||||
pipe_command.o: ../../include/stringops.h
|
||||
|
@ -278,7 +278,7 @@ int db_common_expand(void *ctxArg, const char *format, const char *value,
|
||||
db_quote_callback_t quote_func)
|
||||
{
|
||||
char *myname = "db_common_expand";
|
||||
DB_COMMON_CTX *ctx = (DB_COMMON_CTX *)ctxArg;
|
||||
DB_COMMON_CTX *ctx = (DB_COMMON_CTX *) ctxArg;
|
||||
const char *vdomain = 0;
|
||||
const char *kdomain = 0;
|
||||
char *vuser = 0;
|
||||
@ -287,18 +287,28 @@ int db_common_expand(void *ctxArg, const char *format, const char *value,
|
||||
int i;
|
||||
const char *cp;
|
||||
|
||||
/* Skip NULL or empty values */
|
||||
if (value == 0 || *value == 0)
|
||||
return (0);
|
||||
/* Skip NULL values, silently. */
|
||||
if (value == 0)
|
||||
return (0);
|
||||
|
||||
/* Don't silenty skip empty query string or empty lookup results. */
|
||||
if (*value == 0) {
|
||||
if (key)
|
||||
msg_warn("table \"%s:%s\": empty lookup result for: \"%s\""
|
||||
" -- ignored", ctx->dict->type, ctx->dict->name, key);
|
||||
else
|
||||
msg_warn("table \"%s:%s\": empty query string"
|
||||
" -- ignored", ctx->dict->type, ctx->dict->name);
|
||||
return (0);
|
||||
}
|
||||
if (key) {
|
||||
/* This is a result template and the input value is the result */
|
||||
/* This is a result template and the input value is the result */
|
||||
if (ctx->flags & (DB_COMMON_VALUE_DOMAIN | DB_COMMON_VALUE_USER))
|
||||
if ((vdomain = strrchr(value, '@')) != 0)
|
||||
++vdomain;
|
||||
|
||||
if ((!vdomain || !*vdomain) && (ctx->flags&DB_COMMON_VALUE_DOMAIN) != 0
|
||||
|| vdomain == value + 1 && (ctx->flags&DB_COMMON_VALUE_USER) != 0)
|
||||
if ((!vdomain || !*vdomain) && (ctx->flags & DB_COMMON_VALUE_DOMAIN) != 0
|
||||
|| vdomain == value + 1 && (ctx->flags & DB_COMMON_VALUE_USER) != 0)
|
||||
return (0);
|
||||
|
||||
/* The result format may use the local or domain part of the key */
|
||||
@ -307,50 +317,51 @@ int db_common_expand(void *ctxArg, const char *format, const char *value,
|
||||
++kdomain;
|
||||
|
||||
/*
|
||||
* The key should already be checked before the query. No harm if
|
||||
* the query did not get optimized out, so we just issue a warning.
|
||||
* The key should already be checked before the query. No harm if the
|
||||
* query did not get optimized out, so we just issue a warning.
|
||||
*/
|
||||
if ((!kdomain || !*kdomain) && (ctx->flags&DB_COMMON_KEY_DOMAIN) != 0
|
||||
|| kdomain == key + 1 && (ctx->flags & DB_COMMON_KEY_USER) != 0) {
|
||||
if ((!kdomain || !*kdomain) && (ctx->flags & DB_COMMON_KEY_DOMAIN) != 0
|
||||
|| kdomain == key + 1 && (ctx->flags & DB_COMMON_KEY_USER) != 0) {
|
||||
msg_warn("%s: %s: lookup key '%s' skipped after query", myname,
|
||||
ctx->dict->name, value);
|
||||
ctx->dict->name, value);
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
/* This is a query template and the input value is the lookup key */
|
||||
/* This is a query template and the input value is the lookup key */
|
||||
if (ctx->flags & (DB_COMMON_KEY_DOMAIN | DB_COMMON_KEY_USER))
|
||||
if ((vdomain = strrchr(value, '@')) != 0)
|
||||
++vdomain;
|
||||
|
||||
if ((!vdomain || !*vdomain) && (ctx->flags&DB_COMMON_KEY_DOMAIN) != 0
|
||||
|| vdomain == value + 1 && (ctx->flags & DB_COMMON_KEY_USER) != 0)
|
||||
if ((!vdomain || !*vdomain) && (ctx->flags & DB_COMMON_KEY_DOMAIN) != 0
|
||||
|| vdomain == value + 1 && (ctx->flags & DB_COMMON_KEY_USER) != 0)
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (ctx->nparts > 0) {
|
||||
parts = argv_split(key ? kdomain : vdomain, ".");
|
||||
parts = argv_split(key ? kdomain : vdomain, ".");
|
||||
|
||||
/*
|
||||
* Filter out input keys whose domains lack enough labels
|
||||
* to fill-in the query template. See below and also
|
||||
* db_common_parse() which initializes ctx->nparts.
|
||||
* Filter out input keys whose domains lack enough labels to fill-in
|
||||
* the query template. See below and also db_common_parse() which
|
||||
* initializes ctx->nparts.
|
||||
*/
|
||||
if (parts->argc < ctx->nparts) {
|
||||
argv_free(parts);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip domains with leading, consecutive or trailing '.'
|
||||
* separators among the required labels.
|
||||
* Skip domains with leading, consecutive or trailing '.' separators
|
||||
* among the required labels.
|
||||
*/
|
||||
for (i = 0; i < ctx->nparts; i++)
|
||||
if (*parts->argv[parts->argc-i-1] == 0) {
|
||||
if (*parts->argv[parts->argc - i - 1] == 0) {
|
||||
argv_free(parts);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
if (VSTRING_LEN(result) > 0)
|
||||
VSTRING_ADDCH(result, ',');
|
||||
VSTRING_ADDCH(result, ',');
|
||||
|
||||
#define QUOTE_VAL(d, q, v, buf) do { \
|
||||
if (q) \
|
||||
@ -360,9 +371,9 @@ int db_common_expand(void *ctxArg, const char *format, const char *value,
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Replace all instances of %s with the address to look up. Replace
|
||||
* %u with the user portion, and %d with the domain portion. "%%"
|
||||
* expands to "%". lowercase -> addr, uppercase -> key
|
||||
* Replace all instances of %s with the address to look up. Replace %u
|
||||
* with the user portion, and %d with the domain portion. "%%" expands to
|
||||
* "%". lowercase -> addr, uppercase -> key
|
||||
*/
|
||||
for (cp = format; *cp; cp++) {
|
||||
if (*cp == '%') {
|
||||
@ -381,8 +392,7 @@ int db_common_expand(void *ctxArg, const char *format, const char *value,
|
||||
if (vuser == 0)
|
||||
vuser = mystrndup(value, vdomain - value - 1);
|
||||
QUOTE_VAL(ctx->dict, quote_func, vuser, result);
|
||||
}
|
||||
else
|
||||
} else
|
||||
QUOTE_VAL(ctx->dict, quote_func, value, result);
|
||||
break;
|
||||
|
||||
@ -391,7 +401,7 @@ int db_common_expand(void *ctxArg, const char *format, const char *value,
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
if (key)
|
||||
if (key)
|
||||
QUOTE_VAL(ctx->dict, quote_func, key, result);
|
||||
else
|
||||
QUOTE_VAL(ctx->dict, quote_func, value, result);
|
||||
@ -403,16 +413,14 @@ int db_common_expand(void *ctxArg, const char *format, const char *value,
|
||||
if (kuser == 0)
|
||||
kuser = mystrndup(key, kdomain - key - 1);
|
||||
QUOTE_VAL(ctx->dict, quote_func, kuser, result);
|
||||
}
|
||||
else
|
||||
} else
|
||||
QUOTE_VAL(ctx->dict, quote_func, key, result);
|
||||
} else {
|
||||
if (vdomain) {
|
||||
if (vuser == 0)
|
||||
vuser = mystrndup(value, vdomain - value - 1);
|
||||
QUOTE_VAL(ctx->dict, quote_func, vuser, result);
|
||||
}
|
||||
else
|
||||
} else
|
||||
QUOTE_VAL(ctx->dict, quote_func, value, result);
|
||||
}
|
||||
break;
|
||||
@ -424,18 +432,26 @@ int db_common_expand(void *ctxArg, const char *format, const char *value,
|
||||
QUOTE_VAL(ctx->dict, quote_func, vdomain, result);
|
||||
break;
|
||||
|
||||
case '1': case '2': case '3': case '4': case '5':
|
||||
case '6': case '7': case '8': case '9':
|
||||
/*
|
||||
* Interpolate %[1-9] components into the query string.
|
||||
* By this point db_common_parse() has identified the
|
||||
* highest component index, and (see above) keys with
|
||||
* fewer components have been filtered out. The "parts"
|
||||
* ARGV is guaranteed to be initialized and hold enough
|
||||
* elements to satisfy the query template.
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
|
||||
/*
|
||||
* Interpolate %[1-9] components into the query string. By
|
||||
* this point db_common_parse() has identified the highest
|
||||
* component index, and (see above) keys with fewer
|
||||
* components have been filtered out. The "parts" ARGV is
|
||||
* guaranteed to be initialized and hold enough elements to
|
||||
* satisfy the query template.
|
||||
*/
|
||||
QUOTE_VAL(ctx->dict, quote_func,
|
||||
parts->argv[parts->argc-(*cp-'0')], result);
|
||||
parts->argv[parts->argc - (*cp - '0')], result);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -449,11 +465,11 @@ int db_common_expand(void *ctxArg, const char *format, const char *value,
|
||||
VSTRING_TERMINATE(result);
|
||||
|
||||
if (vuser)
|
||||
myfree(vuser);
|
||||
myfree(vuser);
|
||||
if (kuser)
|
||||
myfree(kuser);
|
||||
myfree(kuser);
|
||||
if (parts)
|
||||
argv_free(parts);
|
||||
argv_free(parts);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
@ -870,7 +870,7 @@ extern char *var_bestmx_transp;
|
||||
|
||||
#define VAR_SMTP_CACHE_CONNT "smtp_connection_cache_time_limit"
|
||||
#define DEF_SMTP_CACHE_CONNT "2s"
|
||||
#define VAR_LMTP_CACHE_CONNT "smtp_connection_cache_time_limit"
|
||||
#define VAR_LMTP_CACHE_CONNT "lmtp_connection_cache_time_limit"
|
||||
#define DEF_LMTP_CACHE_CONNT "2s"
|
||||
extern int var_smtp_cache_conn;
|
||||
|
||||
|
@ -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 "20060325"
|
||||
#define MAIL_RELEASE_DATE "20060403"
|
||||
#define MAIL_VERSION_NUMBER "2.3"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@ -44,8 +44,14 @@
|
||||
/* The command is specified as an argument vector. This vector is
|
||||
/* passed without further inspection to the \fIexecvp\fR() routine.
|
||||
/* One of PIPE_CMD_COMMAND or PIPE_CMD_ARGV must be specified.
|
||||
/* .IP "PIPE_CMD_CHROOT (char *)"
|
||||
/* Root and working directory for command execution. This takes
|
||||
/* effect before PIPE_CMD_CWD. A null pointer means don't
|
||||
/* change root and working directory anyway. Failure to change
|
||||
/* directory causes mail delivery to be deferred.
|
||||
/* .IP "PIPE_CMD_CWD (char *)"
|
||||
/* Working directory for command execution. A null pointer means
|
||||
/* Working directory for command execution, after changing process
|
||||
/* privileges to PIPE_CMD_UID and PIPE_CMD_GID. A null pointer means
|
||||
/* don't change directory anyway. Failure to change directory
|
||||
/* causes mail delivery to be deferred.
|
||||
/* .IP "PIPE_CMD_ENV (char **)"
|
||||
@ -137,6 +143,7 @@
|
||||
|
||||
#include <msg.h>
|
||||
#include <vstream.h>
|
||||
#include <msg_vstream.h>
|
||||
#include <vstring.h>
|
||||
#include <stringops.h>
|
||||
#include <iostuff.h>
|
||||
@ -144,6 +151,7 @@
|
||||
#include <set_ugid.h>
|
||||
#include <set_eugid.h>
|
||||
#include <argv.h>
|
||||
#include <chroot_uid.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
@ -172,6 +180,7 @@ struct pipe_args {
|
||||
char **export; /* exportable environment */
|
||||
char *shell; /* command shell */
|
||||
char *cwd; /* preferred working directory */
|
||||
char *chroot; /* root directory */
|
||||
};
|
||||
|
||||
static int pipe_command_timeout; /* command has timed out */
|
||||
@ -200,6 +209,7 @@ static void get_pipe_args(struct pipe_args * args, va_list ap)
|
||||
args->export = 0;
|
||||
args->shell = 0;
|
||||
args->cwd = 0;
|
||||
args->chroot = 0;
|
||||
|
||||
pipe_command_maxtime = var_command_maxtime;
|
||||
|
||||
@ -254,6 +264,9 @@ static void get_pipe_args(struct pipe_args * args, va_list ap)
|
||||
case PIPE_CMD_CWD:
|
||||
args->cwd = va_arg(ap, char *);
|
||||
break;
|
||||
case PIPE_CMD_CHROOT:
|
||||
args->chroot = va_arg(ap, char *);
|
||||
break;
|
||||
default:
|
||||
msg_panic("%s: unknown key: %d", myname, key);
|
||||
}
|
||||
@ -357,14 +370,22 @@ static int pipe_command_wait_or_kill(pid_t pid, WAIT_STATUS_T *statusp, int sig,
|
||||
|
||||
static void pipe_child_cleanup(void)
|
||||
{
|
||||
exit(EX_TEMPFAIL);
|
||||
|
||||
/*
|
||||
* WARNING: don't place code here. This code may run as mail_owner, as
|
||||
* root, or as the user/group specified with the "user" attribute. The
|
||||
* only safe action is to terminate.
|
||||
*
|
||||
* Future proofing. If you need exit() here then you broke Postfix.
|
||||
*/
|
||||
_exit(EX_TEMPFAIL);
|
||||
}
|
||||
|
||||
/* pipe_command - execute command with extreme prejudice */
|
||||
|
||||
int pipe_command(VSTREAM *src, DSN_BUF *why,...)
|
||||
{
|
||||
char *myname = "pipe_comand";
|
||||
char *myname = "pipe_command";
|
||||
va_list ap;
|
||||
VSTREAM *cmd_in_stream;
|
||||
VSTREAM *cmd_out_stream;
|
||||
@ -448,6 +469,28 @@ int pipe_command(VSTREAM *src, DSN_BUF *why,...)
|
||||
*/
|
||||
case 0:
|
||||
(void) msg_cleanup(pipe_child_cleanup);
|
||||
|
||||
/*
|
||||
* In order to chroot it is necessary to switch euid back to root.
|
||||
* Right after chroot we call set_ugid() so all privileges will be
|
||||
* dropped again.
|
||||
*
|
||||
* XXX For consistency we use chroot_uid() to change root+current
|
||||
* directory. However, we must not use chroot_uid() to change process
|
||||
* privileges (assuming a version that accepts numeric privileges).
|
||||
* That would create a maintenance problem, because we would have two
|
||||
* different code paths to set the external command's privileges.
|
||||
*/
|
||||
if (args.chroot) {
|
||||
seteuid(0);
|
||||
chroot_uid(args.chroot, (char *) 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX If we put code before the set_ugid() call, then the code that
|
||||
* changes root directory must switch back to the mail_owner UID,
|
||||
* otherwise we'd be running with root privileges.
|
||||
*/
|
||||
set_ugid(args.uid, args.gid);
|
||||
if (setsid() < 0)
|
||||
msg_warn("setsid failed: %m");
|
||||
@ -488,12 +531,15 @@ int pipe_command(VSTREAM *src, DSN_BUF *why,...)
|
||||
/*
|
||||
* Process plumbing. If possible, avoid running a shell.
|
||||
*
|
||||
* From this point we would like to handle fatal errors ourselves
|
||||
* (ENOMEM would probably be one of the few soft error conditions).
|
||||
* For that we have to update exec_command() first so it returns an
|
||||
* error indication instead of terminating the process.
|
||||
* As a safety for buggy libraries, we close the syslog socket.
|
||||
* Otherwise we could leak a file descriptor that was created by a
|
||||
* privileged process.
|
||||
*
|
||||
* XXX To avoid losing fatal error messages we open a VSTREAM and
|
||||
* capture the output in the parent process.
|
||||
*/
|
||||
closelog();
|
||||
msg_vstream_init(var_procname, VSTREAM_ERR);
|
||||
if (args.argv) {
|
||||
execvp(args.argv[0], args.argv);
|
||||
msg_fatal("%s: execvp %s: %m", myname, args.argv[0]);
|
||||
@ -605,7 +651,10 @@ int pipe_command(VSTREAM *src, DSN_BUF *why,...)
|
||||
return (sp->dsn[0] == '4' ?
|
||||
PIPE_STAT_DEFER : PIPE_STAT_BOUNCE);
|
||||
}
|
||||
/* No "D.S.N text" or <sysexits.h> compatible status. Fake it. */
|
||||
|
||||
/*
|
||||
* No "D.S.N text" or <sysexits.h> compatible status. Fake it.
|
||||
*/
|
||||
else {
|
||||
sp = sys_exits_detail(WEXITSTATUS(wait_status));
|
||||
dsb_unix(why, sp->dsn,
|
||||
|
@ -41,6 +41,7 @@
|
||||
#define PIPE_CMD_EXPORT 12 /* exportable environment */
|
||||
#define PIPE_CMD_ORIG_RCPT 13 /* mail_copy() original recipient */
|
||||
#define PIPE_CMD_CWD 14 /* working directory */
|
||||
#define PIPE_CMD_CHROOT 15 /* chroot() before exec() */
|
||||
|
||||
/*
|
||||
* Command completion status.
|
||||
|
@ -41,8 +41,19 @@
|
||||
/* .fi
|
||||
/* The external command attributes are given in the \fBmaster.cf\fR
|
||||
/* file at the end of a service definition. The syntax is as follows:
|
||||
/* .IP "\fBdirectory=\fIpathname\fR (optional, default: \fB$queue_directory\fR)"
|
||||
/* .IP "\fBchroot=\fIpathname\fR (optional)"
|
||||
/* Change the process root directory and working directory to
|
||||
/* the named directory. This happens before switching to the
|
||||
/* privileges specified with the \fBuser\fR attribute, and
|
||||
/* before executing the optional \fBdirectory=\fIpathname\fR
|
||||
/* directive. Delivery is deferred in case of failure.
|
||||
/* .sp
|
||||
/* This feature is available as of Postfix 2.3.
|
||||
/* .IP "\fBdirectory=\fIpathname\fR (optional)"
|
||||
/* Change to the named directory before executing the external command.
|
||||
/* The directory must be accessible for the user specified with the
|
||||
/* \fBuser\fR attribute (see below).
|
||||
/* The default working directory is \fB$queue_directory\fR.
|
||||
/* Delivery is deferred in case of failure.
|
||||
/* .sp
|
||||
/* This feature is available as of Postfix 2.2.
|
||||
@ -138,7 +149,7 @@
|
||||
/* be returned to the sender as undeliverable.
|
||||
/* .IP "\fBuser\fR=\fIusername\fR (required)"
|
||||
/* .IP "\fBuser\fR=\fIusername\fR:\fIgroupname\fR"
|
||||
/* The external command is executed with the rights of the
|
||||
/* Execute the external command with the rights of the
|
||||
/* specified \fIusername\fR. The software refuses to execute
|
||||
/* commands with root privileges, or with the privileges of the
|
||||
/* mail system owner. If \fIgroupname\fR is specified, the
|
||||
@ -474,6 +485,7 @@ typedef struct {
|
||||
gid_t gid; /* command privileges */
|
||||
int flags; /* mail_copy() flags */
|
||||
char *exec_dir; /* working directory */
|
||||
char *chroot_dir; /* chroot directory */
|
||||
VSTRING *eol; /* output record delimiter */
|
||||
VSTRING *null_sender; /* null sender expansion */
|
||||
off_t size_limit; /* max size in bytes we will accept */
|
||||
@ -728,6 +740,7 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
|
||||
attr->command = 0;
|
||||
attr->flags = 0;
|
||||
attr->exec_dir = 0;
|
||||
attr->chroot_dir = 0;
|
||||
attr->eol = vstring_strcpy(vstring_alloc(1), "\n");
|
||||
attr->null_sender = vstring_strcpy(vstring_alloc(1), MAIL_ADDR_MAIL_DAEMON);
|
||||
attr->size_limit = 0;
|
||||
@ -807,6 +820,13 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
|
||||
attr->exec_dir = mystrdup(*argv + sizeof("directory=") - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* chroot=string
|
||||
*/
|
||||
else if (strncasecmp("chroot=", *argv, sizeof("chroot=") - 1) == 0) {
|
||||
attr->chroot_dir = mystrdup(*argv + sizeof("chroot=") - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* eol=string
|
||||
*/
|
||||
@ -1105,6 +1125,7 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
|
||||
PIPE_CMD_EOL, STR(attr.eol),
|
||||
PIPE_CMD_EXPORT, export_env->argv,
|
||||
PIPE_CMD_CWD, attr.exec_dir,
|
||||
PIPE_CMD_CHROOT, attr.chroot_dir,
|
||||
PIPE_CMD_ORIG_RCPT, rcpt_list->info[0].orig_addr,
|
||||
PIPE_CMD_DELIVERED, rcpt_list->info[0].address,
|
||||
PIPE_CMD_END);
|
||||
|
@ -107,7 +107,9 @@ int myflock(int fd, int lock_style, int operation)
|
||||
-1, LOCK_SH | LOCK_NB, LOCK_EX | LOCK_NB, -1
|
||||
};
|
||||
|
||||
status = flock(fd, lock_ops[operation]);
|
||||
while ((status = flock(fd, lock_ops[operation])) < 0
|
||||
&& errno == EINTR)
|
||||
sleep(1);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -129,8 +131,7 @@ int myflock(int fd, int lock_style, int operation)
|
||||
lock.l_type = lock_ops[operation & ~MYFLOCK_OP_NOWAIT];
|
||||
request = (operation & MYFLOCK_OP_NOWAIT) ? F_SETLK : F_SETLKW;
|
||||
while ((status = fcntl(fd, request, &lock)) < 0
|
||||
&& request == F_SETLKW
|
||||
&& (errno == EINTR || errno == ENOLCK || errno == EDEADLK))
|
||||
&& errno == EINTR)
|
||||
sleep(1);
|
||||
break;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user