mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 21:55:20 +00:00
postfix-2.5-20071203
This commit is contained in:
committed by
Viktor Dukhovni
parent
93d0a26a92
commit
a98fc88914
@@ -13878,3 +13878,22 @@ Apologies for any names omitted.
|
||||
|
||||
Bugfix: don't update the back-to-back delivery time stamp
|
||||
while deferring mail. File: *qmgr/qmgr_entry.c.
|
||||
|
||||
20071203
|
||||
|
||||
Feature: support for read-write tables in the proxymap
|
||||
service. This is implemented with a separate master.cf entry
|
||||
named "proxywrite" that should run with process limit of 1
|
||||
if you want to update Berkeley DB like tables. This feature
|
||||
requires that tables be authorized with the proxy_write_maps
|
||||
configuration parameter. Files: global/dict_procy.[hc],
|
||||
proxymap/proxymap.c.
|
||||
|
||||
Human factors: the postmap and postalias commands now produce
|
||||
nicer diagnostics when asked to do something with a proxied
|
||||
map that they can't do. Files: postmap/postmap.c,
|
||||
postalias/postalias.c.
|
||||
|
||||
Bugfix: the proxymap client didn't properly propagate the
|
||||
postmap (postalias) -r and -w options to the proxymap server.
|
||||
File: util/dict.h.
|
||||
|
@@ -17,6 +17,14 @@ Incompatibility with Postfix 2.3 and earlier
|
||||
If you upgrade from Postfix 2.3 or earlier, read RELEASE_NOTES-2.4
|
||||
before proceeding.
|
||||
|
||||
Incompatibility with Postfix snapshot 20071203
|
||||
==============================================
|
||||
|
||||
The "make upgrade" procedure adds a new service "proxywrite" to the
|
||||
master.cf file, for read/write lookup table access. If you copy
|
||||
your old configuration file over the updated one, you will have
|
||||
to run "postfix upgrade-configuration" again.
|
||||
|
||||
Major changes with Postfix snapshot 20071202
|
||||
============================================
|
||||
|
||||
|
@@ -659,6 +659,15 @@ retry unix - - n - - error
|
||||
EOF
|
||||
}
|
||||
|
||||
# Add missing proxywrite service to master.cf.
|
||||
|
||||
grep '^proxywrite.*proxymap' $config_directory/master.cf >/dev/null || {
|
||||
echo Editing $config_directory/master.cf, adding missing entry for proxywrite service
|
||||
cat >>$config_directory/master.cf <<EOF || exit 1
|
||||
proxywrite unix - - n - 1 proxymap
|
||||
EOF
|
||||
}
|
||||
|
||||
# Report (but do not remove) obsolete files.
|
||||
|
||||
test -n "$obsolete" && {
|
||||
|
@@ -6152,9 +6152,9 @@ Example:
|
||||
(default: see "postconf -d" output)</b></DT><DD>
|
||||
|
||||
<p>
|
||||
The lookup tables that the <a href="proxymap.8.html">proxymap(8)</a> server is allowed to access.
|
||||
Table references that don't begin with <a href="proxymap.8.html">proxy</a>: are ignored. The
|
||||
<a href="proxymap.8.html">proxymap(8)</a> table accesses are read-only.
|
||||
The lookup tables that the <a href="proxymap.8.html">proxymap(8)</a> server is allowed to
|
||||
access for the read-only service.
|
||||
Table references that don't begin with <a href="proxymap.8.html">proxy</a>: are ignored.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -6162,6 +6162,22 @@ This feature is available in Postfix 2.0 and later.
|
||||
</p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="proxy_write_maps">proxy_write_maps</a>
|
||||
(default: see "postconf -d" output)</b></DT><DD>
|
||||
|
||||
<p>
|
||||
The lookup tables that the <a href="proxymap.8.html">proxymap(8)</a> server is allowed to
|
||||
access for the read-write service.
|
||||
Table references that don't begin with <a href="proxymap.8.html">proxy</a>: are ignored.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This feature is available in Postfix 2.5 and later.
|
||||
</p>
|
||||
|
||||
|
||||
</DD>
|
||||
|
||||
<DT><b><a name="qmgr_clog_warn_time">qmgr_clog_warn_time</a>
|
||||
|
@@ -13,8 +13,10 @@ PROXYMAP(8) PROXYMAP(8)
|
||||
<b>proxymap</b> [generic Postfix daemon options]
|
||||
|
||||
<b>DESCRIPTION</b>
|
||||
The <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server provides read-only table lookup
|
||||
service to Postfix processes. The purpose of the service
|
||||
The <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server provides read-only or read-write
|
||||
table lookup service to Postfix processes. These services
|
||||
are implemented with distinct service names: <b>proxymap</b> and
|
||||
<b>proxywrite</b>, respectively. The purpose of these services
|
||||
is:
|
||||
|
||||
<b>o</b> To overcome chroot restrictions. For example, a
|
||||
@@ -39,6 +41,10 @@ PROXYMAP(8) PROXYMAP(8)
|
||||
The total number of connections is limited by the
|
||||
number of proxymap server processes.
|
||||
|
||||
<b>o</b> To provide single-updater functionality for lookup
|
||||
tables that do not reliably support multiple writ-
|
||||
ers (i.e. all file-based tables).
|
||||
|
||||
The <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server implements the following requests:
|
||||
|
||||
<b>open</b> <i>maptype:mapname flags</i>
|
||||
@@ -49,10 +55,26 @@ PROXYMAP(8) PROXYMAP(8)
|
||||
|
||||
<b>lookup</b> <i>maptype:mapname flags key</i>
|
||||
Look up the data stored under the requested key.
|
||||
The reply is the request completion status code
|
||||
(below) and the lookup result value. The <i>map-</i>
|
||||
<i>type:mapname</i> and <i>flags</i> are the same as with the
|
||||
<b>open</b> request.
|
||||
The reply is the request completion status code and
|
||||
the lookup result value. The <i>maptype:mapname</i> and
|
||||
<i>flags</i> are the same as with the <b>open</b> request.
|
||||
|
||||
<b>update</b> <i>maptype:mapname flags key value</i>
|
||||
Update the data stored under the requested key.
|
||||
The reply is the request completion status code.
|
||||
The <i>maptype:mapname</i> and <i>flags</i> are the same as with
|
||||
the <b>open</b> request.
|
||||
|
||||
To implement single-updater maps, specify a process
|
||||
limit of 1 in the <a href="master.5.html">master.cf</a> file entry for the
|
||||
proxywrite service.
|
||||
|
||||
This request is supported in Postfix 2.5 and later.
|
||||
|
||||
The request completion status is one of OK, RETRY, NOKEY
|
||||
(lookup failed because the key was not found), BAD (mal-
|
||||
formed request) or DENY (the table is not approved for
|
||||
proxy read or update access).
|
||||
|
||||
There is no <b>close</b> command, nor are tables implicitly
|
||||
closed when a client disconnects. The purpose is to share
|
||||
@@ -69,11 +91,11 @@ PROXYMAP(8) PROXYMAP(8)
|
||||
|
||||
<b>SECURITY</b>
|
||||
The <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server opens only tables that are approved
|
||||
via the <b><a href="postconf.5.html#proxy_read_maps">proxy_read_maps</a></b> configuration parameter, does not
|
||||
talk to users, and can run at fixed low privilege,
|
||||
chrooted or not. However, running the proxymap server
|
||||
chrooted severely limits usability, because it can open
|
||||
only chrooted tables.
|
||||
via the <b><a href="postconf.5.html#proxy_read_maps">proxy_read_maps</a></b> or <b><a href="postconf.5.html#proxy_write_maps">proxy_write_maps</a></b> configuration
|
||||
parameters, does not talk to users, and can run at fixed
|
||||
low privilege, chrooted or not. However, running the
|
||||
proxymap server chrooted severely limits usability,
|
||||
because it can open only chrooted tables.
|
||||
|
||||
The <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server is not a trusted daemon process,
|
||||
and must not be used to look up sensitive information such
|
||||
@@ -94,6 +116,16 @@ PROXYMAP(8) PROXYMAP(8)
|
||||
clients, and must therefore not be used for tables that
|
||||
have high-latency lookups.
|
||||
|
||||
The <a href="proxymap.8.html"><b>proxymap</b>(8)</a> read-write service does not explicitly
|
||||
close lookup tables (even if it did, this could not be
|
||||
relied on, because the process may be terminated between
|
||||
table updates). The read-write service should therefore
|
||||
not be used with tables that leave persistent storage in
|
||||
an inconsistent state between updates (for example, CDB).
|
||||
Tables that support "sync on update" should be safe (for
|
||||
example, Berkeley DB) as should tables that are imple-
|
||||
mented by a real DBMS.
|
||||
|
||||
<b>CONFIGURATION PARAMETERS</b>
|
||||
On busy mail systems a long time may pass before <a href="proxymap.8.html"><b>prox-</b></a>
|
||||
<a href="proxymap.8.html"><b>ymap</b>(8)</a> relevant changes to <a href="postconf.5.html"><b>main.cf</b></a> are picked up. Use the
|
||||
@@ -135,7 +167,13 @@ PROXYMAP(8) PROXYMAP(8)
|
||||
|
||||
<b><a href="postconf.5.html#proxy_read_maps">proxy_read_maps</a> (see 'postconf -d' output)</b>
|
||||
The lookup tables that the <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server is
|
||||
allowed to access.
|
||||
allowed to access for the read-only service.
|
||||
|
||||
Available in Postfix 2.5 and later:
|
||||
|
||||
<b><a href="postconf.5.html#proxy_write_maps">proxy_write_maps</a> (see 'postconf -d' output)</b>
|
||||
The lookup tables that the <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server is
|
||||
allowed to access for the read-write service.
|
||||
|
||||
<b>SEE ALSO</b>
|
||||
<a href="postconf.5.html">postconf(5)</a>, configuration parameters
|
||||
@@ -145,7 +183,7 @@ PROXYMAP(8) PROXYMAP(8)
|
||||
<a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
|
||||
|
||||
<b>LICENSE</b>
|
||||
The Secure Mailer license must be distributed with this
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>HISTORY</b>
|
||||
|
@@ -3423,11 +3423,17 @@ proxy_interfaces = 1.2.3.4
|
||||
.ad
|
||||
.ft R
|
||||
.SH proxy_read_maps (default: see "postconf -d" output)
|
||||
The lookup tables that the \fBproxymap\fR(8) server is allowed to access.
|
||||
Table references that don't begin with proxy: are ignored. The
|
||||
\fBproxymap\fR(8) table accesses are read-only.
|
||||
The lookup tables that the \fBproxymap\fR(8) server is allowed to
|
||||
access for the read-only service.
|
||||
Table references that don't begin with proxy: are ignored.
|
||||
.PP
|
||||
This feature is available in Postfix 2.0 and later.
|
||||
.SH proxy_write_maps (default: see "postconf -d" output)
|
||||
The lookup tables that the \fBproxymap\fR(8) server is allowed to
|
||||
access for the read-write service.
|
||||
Table references that don't begin with proxy: are ignored.
|
||||
.PP
|
||||
This feature is available in Postfix 2.5 and later.
|
||||
.SH qmgr_clog_warn_time (default: 300s)
|
||||
The minimal delay between warnings that a specific destination is
|
||||
clogging up the Postfix active queue. Specify 0 to disable.
|
||||
|
@@ -12,9 +12,10 @@ Postfix lookup table proxy server
|
||||
.SH DESCRIPTION
|
||||
.ad
|
||||
.fi
|
||||
The \fBproxymap\fR(8) server provides read-only table
|
||||
lookup service to Postfix processes. The purpose
|
||||
of the service is:
|
||||
The \fBproxymap\fR(8) server provides read-only or read-write
|
||||
table lookup service to Postfix processes. These services are
|
||||
implemented with distinct service names: \fBproxymap\fR and
|
||||
\fBproxywrite\fR, respectively. The purpose of these services is:
|
||||
.IP \(bu
|
||||
To overcome chroot restrictions. For example, a chrooted SMTP
|
||||
server needs access to the system passwd file in order to
|
||||
@@ -39,6 +40,10 @@ virtual_alias_maps =
|
||||
.sp
|
||||
The total number of connections is limited by the number of
|
||||
proxymap server processes.
|
||||
.IP \(bu
|
||||
To provide single-updater functionality for lookup tables
|
||||
that do not reliably support multiple writers (i.e. all
|
||||
file-based tables).
|
||||
.PP
|
||||
The \fBproxymap\fR(8) server implements the following requests:
|
||||
.IP "\fBopen\fR \fImaptype:mapname flags\fR"
|
||||
@@ -48,11 +53,26 @@ dependent flags (to distinguish a fixed string table from a regular
|
||||
expression table).
|
||||
.IP "\fBlookup\fR \fImaptype:mapname flags key\fR"
|
||||
Look up the data stored under the requested key.
|
||||
The reply is the request completion status code (below) and
|
||||
The reply is the request completion status code and
|
||||
the lookup result value.
|
||||
The \fImaptype:mapname\fR and \fIflags\fR are the same
|
||||
as with the \fBopen\fR request.
|
||||
.IP "\fBupdate\fR \fImaptype:mapname flags key value\fR"
|
||||
Update the data stored under the requested key.
|
||||
The reply is the request completion status code.
|
||||
The \fImaptype:mapname\fR and \fIflags\fR are the same
|
||||
as with the \fBopen\fR request.
|
||||
.sp
|
||||
To implement single-updater maps, specify a process limit
|
||||
of 1 in the master.cf file entry for the proxywrite service.
|
||||
.sp
|
||||
This request is supported in Postfix 2.5 and later.
|
||||
.PP
|
||||
The request completion status is one of OK, RETRY, NOKEY
|
||||
(lookup failed because the key was not found), BAD (malformed
|
||||
request) or DENY (the table is not approved for proxy read
|
||||
or update access).
|
||||
|
||||
There is no \fBclose\fR command, nor are tables implicitly closed
|
||||
when a client disconnects. The purpose is to share tables among
|
||||
multiple client processes.
|
||||
@@ -74,8 +94,9 @@ or after \fB$max_idle\fR seconds of idle time.
|
||||
.nf
|
||||
.ad
|
||||
.fi
|
||||
The \fBproxymap\fR(8) server opens only tables that are approved via the
|
||||
\fBproxy_read_maps\fR configuration parameter, does not talk to
|
||||
The \fBproxymap\fR(8) server opens only tables that are
|
||||
approved via the \fBproxy_read_maps\fR or \fBproxy_write_maps\fR
|
||||
configuration parameters, does not talk to
|
||||
users, and can run at fixed low privilege, chrooted or not.
|
||||
However, running the proxymap server chrooted severely limits
|
||||
usability, because it can open only chrooted tables.
|
||||
@@ -98,6 +119,15 @@ Problems and transactions are logged to \fBsyslogd\fR(8).
|
||||
The \fBproxymap\fR(8) server provides service to multiple clients,
|
||||
and must therefore not be used for tables that have high-latency
|
||||
lookups.
|
||||
|
||||
The \fBproxymap\fR(8) read-write service does not explicitly
|
||||
close lookup tables (even if it did, this could not be relied on,
|
||||
because the process may be terminated between table updates).
|
||||
The read-write service should therefore not be used with tables that
|
||||
leave persistent storage in an inconsistent state between
|
||||
updates (for example, CDB). Tables that support "sync on
|
||||
update" should be safe (for example, Berkeley DB) as should
|
||||
tables that are implemented by a real DBMS.
|
||||
.SH "CONFIGURATION PARAMETERS"
|
||||
.na
|
||||
.nf
|
||||
@@ -130,7 +160,13 @@ The process ID of a Postfix command or daemon process.
|
||||
.IP "\fBprocess_name (read-only)\fR"
|
||||
The process name of a Postfix command or daemon process.
|
||||
.IP "\fBproxy_read_maps (see 'postconf -d' output)\fR"
|
||||
The lookup tables that the \fBproxymap\fR(8) server is allowed to access.
|
||||
The lookup tables that the \fBproxymap\fR(8) server is allowed to
|
||||
access for the read-only service.
|
||||
.PP
|
||||
Available in Postfix 2.5 and later:
|
||||
.IP "\fBproxy_write_maps (see 'postconf -d' output)\fR"
|
||||
The lookup tables that the \fBproxymap\fR(8) server is allowed to
|
||||
access for the read-write service.
|
||||
.SH "SEE ALSO"
|
||||
.na
|
||||
.nf
|
||||
|
@@ -328,6 +328,7 @@ while (<>) {
|
||||
s;\bpropagate_unmatched_extensions\b;<a href="postconf.5.html#propagate_unmatched_extensions">$&</a>;g;
|
||||
s;\bproxy_inter[-</bB>]*\n* *[<bB>]*faces\b;<a href="postconf.5.html#proxy_interfaces">$&</a>;g;
|
||||
s;\bproxy_read_maps\b;<a href="postconf.5.html#proxy_read_maps">$&</a>;g;
|
||||
s;\bproxy_write_maps\b;<a href="postconf.5.html#proxy_write_maps">$&</a>;g;
|
||||
s;\bqmgr_clog_warn_time\b;<a href="postconf.5.html#qmgr_clog_warn_time">$&</a>;g;
|
||||
s;\bqmgr_fudge_factor\b;<a href="postconf.5.html#qmgr_fudge_factor">$&</a>;g;
|
||||
s;\bqmgr_message_active_limit\b;<a href="postconf.5.html#qmgr_message_active_limit">$&</a>;g;
|
||||
|
@@ -7204,15 +7204,27 @@ This is a read-only parameter.
|
||||
%PARAM proxy_read_maps see "postconf -d" output
|
||||
|
||||
<p>
|
||||
The lookup tables that the proxymap(8) server is allowed to access.
|
||||
Table references that don't begin with proxy: are ignored. The
|
||||
proxymap(8) table accesses are read-only.
|
||||
The lookup tables that the proxymap(8) server is allowed to
|
||||
access for the read-only service.
|
||||
Table references that don't begin with proxy: are ignored.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This feature is available in Postfix 2.0 and later.
|
||||
</p>
|
||||
|
||||
%PARAM proxy_write_maps see "postconf -d" output
|
||||
|
||||
<p>
|
||||
The lookup tables that the proxymap(8) server is allowed to
|
||||
access for the read-write service.
|
||||
Table references that don't begin with proxy: are ignored.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This feature is available in Postfix 2.5 and later.
|
||||
</p>
|
||||
|
||||
%PARAM qmgr_clog_warn_time 300s
|
||||
|
||||
<p>
|
||||
|
@@ -28,7 +28,7 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \
|
||||
tok822_resolve.c tok822_rewrite.c tok822_tree.c trace.c \
|
||||
user_acl.c valid_mailhost_addr.c verify.c verify_clnt.c \
|
||||
verp_sender.c wildcard_inet_addr.c xtext.c delivered_hdr.c \
|
||||
fold_addr.c header_body_checks.c
|
||||
fold_addr.c header_body_checks.c mkmap_proxy.c
|
||||
OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
|
||||
canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
|
||||
clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
|
||||
@@ -58,7 +58,7 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
|
||||
tok822_resolve.o tok822_rewrite.o tok822_tree.o trace.o \
|
||||
user_acl.o valid_mailhost_addr.o verify.o verify_clnt.o \
|
||||
verp_sender.o wildcard_inet_addr.o xtext.o delivered_hdr.o \
|
||||
fold_addr.o header_body_checks.o
|
||||
fold_addr.o header_body_checks.o mkmap_proxy.o
|
||||
HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
|
||||
canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
|
||||
conv_time.h db_common.h debug_peer.h debug_process.h defer.h \
|
||||
@@ -1451,8 +1451,19 @@ mkmap_open.o: ../../include/sys_defs.h
|
||||
mkmap_open.o: ../../include/vbuf.h
|
||||
mkmap_open.o: ../../include/vstream.h
|
||||
mkmap_open.o: ../../include/vstring.h
|
||||
mkmap_open.o: dict_proxy.h
|
||||
mkmap_open.o: mkmap.h
|
||||
mkmap_open.o: mkmap_open.c
|
||||
mkmap_proxy.o: ../../include/argv.h
|
||||
mkmap_proxy.o: ../../include/dict.h
|
||||
mkmap_proxy.o: ../../include/mymalloc.h
|
||||
mkmap_proxy.o: ../../include/sys_defs.h
|
||||
mkmap_proxy.o: ../../include/vbuf.h
|
||||
mkmap_proxy.o: ../../include/vstream.h
|
||||
mkmap_proxy.o: ../../include/vstring.h
|
||||
mkmap_proxy.o: dict_proxy.h
|
||||
mkmap_proxy.o: mkmap.h
|
||||
mkmap_proxy.o: mkmap_proxy.c
|
||||
mkmap_sdbm.o: ../../include/argv.h
|
||||
mkmap_sdbm.o: ../../include/dict.h
|
||||
mkmap_sdbm.o: ../../include/dict_sdbm.h
|
||||
|
@@ -14,7 +14,10 @@
|
||||
/* dict_proxy_open() relays read-only operations through
|
||||
/* the Postfix proxymap server.
|
||||
/*
|
||||
/* The \fIopen_flags\fR argument must specify O_RDONLY.
|
||||
/* The \fIopen_flags\fR argument must specify O_RDONLY
|
||||
/* or O_RDWR|O_CREAT. Depending on this, the client
|
||||
/* connects to the proxymap multiserver or to the
|
||||
/* proxywrite single updater.
|
||||
/*
|
||||
/* The connection to the Postfix proxymap server is automatically
|
||||
/* closed after $ipc_idle seconds of idle time, or after $ipc_ttl
|
||||
@@ -154,6 +157,69 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key)
|
||||
}
|
||||
}
|
||||
|
||||
/* dict_proxy_update - update table entry */
|
||||
|
||||
static void dict_proxy_update(DICT *dict, const char *key, const char *value)
|
||||
{
|
||||
const char *myname = "dict_proxy_update";
|
||||
DICT_PROXY *dict_proxy = (DICT_PROXY *) dict;
|
||||
VSTREAM *stream;
|
||||
int status;
|
||||
int count = 0;
|
||||
int request_flags;
|
||||
|
||||
/*
|
||||
* The client and server live in separate processes that may start and
|
||||
* terminate independently. We cannot rely on a persistent connection,
|
||||
* let alone on persistent state (such as a specific open table) that is
|
||||
* 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->in_flags & DICT_FLAG_RQST_MASK)
|
||||
| (dict->flags & DICT_FLAG_RQST_MASK);
|
||||
for (;;) {
|
||||
stream = clnt_stream_access(proxy_stream);
|
||||
errno = 0;
|
||||
count += 1;
|
||||
if (attr_print(stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_REQ, PROXY_REQ_UPDATE,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_TABLE, dict->name,
|
||||
ATTR_TYPE_INT, MAIL_ATTR_FLAGS, request_flags,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_KEY, key,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_VALUE, value,
|
||||
ATTR_TYPE_END) != 0
|
||||
|| vstream_fflush(stream)
|
||||
|| attr_scan(stream, ATTR_FLAG_STRICT,
|
||||
ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status,
|
||||
ATTR_TYPE_END) != 1) {
|
||||
if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
|
||||
msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
|
||||
} else {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: table=%s flags=%s key=%s value=%s -> status=%d",
|
||||
myname, dict->name, dict_flags_str(request_flags),
|
||||
key, value, status);
|
||||
switch (status) {
|
||||
case PROXY_STAT_BAD:
|
||||
msg_fatal("%s lookup failed for table \"%s\" key \"%s\": "
|
||||
"invalid request",
|
||||
MAIL_SERVICE_PROXYMAP, dict->name, key);
|
||||
case PROXY_STAT_DENY:
|
||||
msg_fatal("%s update access is not configured for table \"%s\"",
|
||||
MAIL_SERVICE_PROXYMAP, dict->name);
|
||||
case PROXY_STAT_OK:
|
||||
return;
|
||||
default:
|
||||
msg_warn("%s update failed for table \"%s\" key \"%s\": "
|
||||
"unexpected reply status %d",
|
||||
MAIL_SERVICE_PROXYMAP, dict->name, key, status);
|
||||
}
|
||||
}
|
||||
clnt_stream_recover(proxy_stream);
|
||||
sleep(1); /* XXX make configurable */
|
||||
}
|
||||
}
|
||||
|
||||
/* dict_proxy_close - disconnect */
|
||||
|
||||
static void dict_proxy_close(DICT *dict)
|
||||
@@ -178,9 +244,14 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
|
||||
|
||||
/*
|
||||
* Sanity checks.
|
||||
*
|
||||
* XXX A complete implementation would also allow O_RDWR without O_CREAT.
|
||||
* But we must not pass on every possible set of flags to the proxy
|
||||
* server; only sets that make sense. For now, the flags are passed
|
||||
* implicitly by choosing between the proxymap or proxywrite service.
|
||||
*/
|
||||
if (open_flags != O_RDONLY)
|
||||
msg_fatal("%s: %s map open requires O_RDONLY access mode",
|
||||
if (open_flags != O_RDONLY && open_flags != (O_RDWR | O_CREAT))
|
||||
msg_fatal("%s: %s map open requires O_RDONLY or O_RDWR|O_CREAT mode",
|
||||
map, DICT_TYPE_PROXY);
|
||||
|
||||
/*
|
||||
@@ -197,6 +268,7 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
|
||||
dict_proxy = (DICT_PROXY *)
|
||||
dict_alloc(DICT_TYPE_PROXY, map, sizeof(*dict_proxy));
|
||||
dict_proxy->dict.lookup = dict_proxy_lookup;
|
||||
dict_proxy->dict.update = dict_proxy_update;
|
||||
dict_proxy->dict.close = dict_proxy_close;
|
||||
dict_proxy->in_flags = dict_flags;
|
||||
dict_proxy->result = vstring_alloc(10);
|
||||
@@ -207,13 +279,18 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
|
||||
* XXX Use absolute pathname to make this work from non-daemon processes.
|
||||
*/
|
||||
if (proxy_stream == 0) {
|
||||
if (access(MAIL_CLASS_PRIVATE "/" MAIL_SERVICE_PROXYMAP, F_OK) == 0)
|
||||
if (access(open_flags == O_RDONLY ?
|
||||
MAIL_CLASS_PRIVATE "/" MAIL_SERVICE_PROXYMAP :
|
||||
MAIL_CLASS_PRIVATE "/" MAIL_SERVICE_PROXYWRITE,
|
||||
F_OK) == 0)
|
||||
prefix = MAIL_CLASS_PRIVATE;
|
||||
else
|
||||
prefix = kludge = concatenate(var_queue_dir, "/",
|
||||
MAIL_CLASS_PRIVATE, (char *) 0);
|
||||
proxy_stream = clnt_stream_create(prefix,
|
||||
MAIL_SERVICE_PROXYMAP,
|
||||
open_flags == O_RDONLY ?
|
||||
MAIL_SERVICE_PROXYMAP :
|
||||
MAIL_SERVICE_PROXYWRITE,
|
||||
var_ipc_idle_limit,
|
||||
var_ipc_ttl_limit);
|
||||
if (kludge)
|
||||
|
@@ -28,6 +28,7 @@ extern DICT *dict_proxy_open(const char *, int, int);
|
||||
*/
|
||||
#define PROXY_REQ_OPEN "open"
|
||||
#define PROXY_REQ_LOOKUP "lookup"
|
||||
#define PROXY_REQ_UPDATE "update"
|
||||
|
||||
#define PROXY_STAT_OK 0 /* operation succeeded */
|
||||
#define PROXY_STAT_NOKEY 1 /* requested key not found */
|
||||
|
@@ -2014,6 +2014,10 @@ extern int var_local_rcpt_code;
|
||||
" $" VAR_MYNETWORKS
|
||||
extern char *var_proxy_read_maps;
|
||||
|
||||
#define VAR_PROXY_WRITE_MAPS "proxy_write_maps"
|
||||
#define DEF_PROXY_WRITE_MAPS "" /* Add here: "$" VAR_AUTH_FAIL_MAP */
|
||||
extern char *var_proxy_write_maps;
|
||||
|
||||
/*
|
||||
* Other.
|
||||
*/
|
||||
|
@@ -56,6 +56,7 @@
|
||||
#define MAIL_SERVICE_TRACE "trace"
|
||||
#define MAIL_SERVICE_RELAY "relay"
|
||||
#define MAIL_SERVICE_PROXYMAP "proxymap"
|
||||
#define MAIL_SERVICE_PROXYWRITE "proxywrite"
|
||||
#define MAIL_SERVICE_SCACHE "scache"
|
||||
|
||||
/*
|
||||
|
@@ -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 "20071130"
|
||||
#define MAIL_RELEASE_DATE "2007111203"
|
||||
#define MAIL_VERSION_NUMBER "2.5"
|
||||
|
||||
#ifdef SNAPSHOT
|
||||
|
@@ -40,6 +40,7 @@ extern MKMAP *mkmap_cdb_open(const char *);
|
||||
extern MKMAP *mkmap_hash_open(const char *);
|
||||
extern MKMAP *mkmap_btree_open(const char *);
|
||||
extern MKMAP *mkmap_sdbm_open(const char *);
|
||||
extern MKMAP *mkmap_proxy_open(const char *);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@@ -66,6 +66,7 @@
|
||||
#include <dict_cdb.h>
|
||||
#include <dict_dbm.h>
|
||||
#include <dict_sdbm.h>
|
||||
#include <dict_proxy.h>
|
||||
#include <sigdelay.h>
|
||||
#include <mymalloc.h>
|
||||
|
||||
@@ -83,6 +84,7 @@ typedef struct {
|
||||
} MKMAP_OPEN_INFO;
|
||||
|
||||
MKMAP_OPEN_INFO mkmap_types[] = {
|
||||
DICT_TYPE_PROXY, mkmap_proxy_open,
|
||||
#ifdef HAS_CDB
|
||||
DICT_TYPE_CDB, mkmap_cdb_open,
|
||||
#endif
|
||||
|
58
postfix/src/global/mkmap_proxy.c
Normal file
58
postfix/src/global/mkmap_proxy.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* mkmap_proxy 3
|
||||
/* SUMMARY
|
||||
/* create or proxied database
|
||||
/* SYNOPSIS
|
||||
/* #include <mkmap.h>
|
||||
/*
|
||||
/* MKMAP *mkmap_proxy_open(path)
|
||||
/* const char *path;
|
||||
/* DESCRIPTION
|
||||
/* This module implements support for updating proxy databases.
|
||||
/*
|
||||
/* mkmap_proxy_open() is a proxymap-specific helper for the
|
||||
/* more general mkmap_open() routine.
|
||||
/*
|
||||
/* All errors are fatal.
|
||||
/* SEE ALSO
|
||||
/* dict_proxy(3), proxy client interface.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <mymalloc.h>
|
||||
#include <dict_proxy.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "mkmap.h"
|
||||
|
||||
/* mkmap_proxy_open - create or open database */
|
||||
|
||||
MKMAP *mkmap_proxy_open(const char *unused_path)
|
||||
{
|
||||
MKMAP *mkmap = (MKMAP *) mymalloc(sizeof(*mkmap));
|
||||
|
||||
/*
|
||||
* Fill in the generic members.
|
||||
*/
|
||||
mkmap->open = dict_proxy_open;
|
||||
mkmap->after_open = 0;
|
||||
mkmap->after_close = 0;
|
||||
|
||||
return (mkmap);
|
||||
}
|
@@ -304,7 +304,7 @@ void qmgr_queue_throttle(QMGR_QUEUE *queue, DSN *dsn)
|
||||
queue->fail_cohorts += 1.0 / queue->window;
|
||||
if (transport->fail_cohort_limit > 0
|
||||
&& queue->fail_cohorts >= transport->fail_cohort_limit)
|
||||
queue->window = 0;
|
||||
queue->window = QMGR_QUEUE_STAT_THROTTLED;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -83,6 +83,7 @@ depend: $(MAKES)
|
||||
# do not edit below this line - it is generated by 'make depend'
|
||||
postalias.o: ../../include/argv.h
|
||||
postalias.o: ../../include/dict.h
|
||||
postalias.o: ../../include/dict_proxy.h
|
||||
postalias.o: ../../include/mail_conf.h
|
||||
postalias.o: ../../include/mail_dict.h
|
||||
postalias.o: ../../include/mail_params.h
|
||||
|
@@ -239,6 +239,7 @@
|
||||
#include <mail_version.h>
|
||||
#include <mkmap.h>
|
||||
#include <mail_task.h>
|
||||
#include <dict_proxy.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@@ -275,6 +276,8 @@ static void postalias(char *map_type, char *path_name, int postalias_flags,
|
||||
if ((open_flags & O_TRUNC) == 0) {
|
||||
source_fp = VSTREAM_IN;
|
||||
vstream_control(source_fp, VSTREAM_CTL_PATH, "stdin", VSTREAM_CTL_END);
|
||||
} else if (strcmp(map_type, DICT_TYPE_PROXY) == 0) {
|
||||
msg_fatal("can't create maps via the proxy service");
|
||||
} else if ((source_fp = vstream_fopen(path_name, O_RDONLY, 0)) == 0) {
|
||||
msg_fatal("open %s: %m", path_name);
|
||||
}
|
||||
@@ -524,10 +527,14 @@ static int postalias_deletes(VSTREAM *in, char **maps, const int map_count,
|
||||
* Open maps ahead of time.
|
||||
*/
|
||||
dicts = (DICT **) mymalloc(sizeof(*dicts) * map_count);
|
||||
for (n = 0; n < map_count; n++)
|
||||
dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ?
|
||||
for (n = 0; n < map_count; n++) {
|
||||
map_name = split_at(maps[n], ':');
|
||||
if (map_name && strcmp(maps[n], DICT_TYPE_PROXY) == 0)
|
||||
msg_fatal("can't delete map entries via the proxy service");
|
||||
dicts[n] = (map_name != 0 ?
|
||||
dict_open3(maps[n], map_name, O_RDWR, dict_flags) :
|
||||
dict_open3(var_db_type, maps[n], O_RDWR, dict_flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform all requests.
|
||||
@@ -556,6 +563,8 @@ static int postalias_delete(const char *map_type, const char *map_name,
|
||||
DICT *dict;
|
||||
int status;
|
||||
|
||||
if (strcmp(map_type, DICT_TYPE_PROXY) == 0)
|
||||
msg_fatal("can't delete map entries via the proxy service");
|
||||
dict = dict_open3(map_type, map_name, O_RDWR, dict_flags);
|
||||
status = dict_del(dict, key);
|
||||
dict_close(dict);
|
||||
@@ -572,6 +581,8 @@ 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)
|
||||
|
@@ -83,6 +83,7 @@ depend: $(MAKES)
|
||||
# do not edit below this line - it is generated by 'make depend'
|
||||
postmap.o: ../../include/argv.h
|
||||
postmap.o: ../../include/dict.h
|
||||
postmap.o: ../../include/dict_proxy.h
|
||||
postmap.o: ../../include/mail_conf.h
|
||||
postmap.o: ../../include/mail_dict.h
|
||||
postmap.o: ../../include/mail_params.h
|
||||
|
@@ -250,6 +250,7 @@
|
||||
#include <mail_version.h>
|
||||
#include <mkmap.h>
|
||||
#include <mail_task.h>
|
||||
#include <dict_proxy.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@@ -279,6 +280,8 @@ static void postmap(char *map_type, char *path_name, int postmap_flags,
|
||||
if ((open_flags & O_TRUNC) == 0) {
|
||||
source_fp = VSTREAM_IN;
|
||||
vstream_control(source_fp, VSTREAM_CTL_PATH, "stdin", VSTREAM_CTL_END);
|
||||
} else if (strcmp(map_type, DICT_TYPE_PROXY) == 0) {
|
||||
msg_fatal("can't create maps via the proxy service");
|
||||
} else if ((source_fp = vstream_fopen(path_name, O_RDONLY, 0)) == 0) {
|
||||
msg_fatal("open %s: %m", path_name);
|
||||
}
|
||||
@@ -471,10 +474,14 @@ static int postmap_deletes(VSTREAM *in, char **maps, const int map_count,
|
||||
* Open maps ahead of time.
|
||||
*/
|
||||
dicts = (DICT **) mymalloc(sizeof(*dicts) * map_count);
|
||||
for (n = 0; n < map_count; n++)
|
||||
dicts[n] = ((map_name = split_at(maps[n], ':')) != 0 ?
|
||||
for (n = 0; n < map_count; n++) {
|
||||
map_name = split_at(maps[n], ':');
|
||||
if (map_name && strcmp(maps[n], DICT_TYPE_PROXY) == 0)
|
||||
msg_fatal("can't delete map entries via the proxy service");
|
||||
dicts[n] = (map_name != 0 ?
|
||||
dict_open3(maps[n], map_name, O_RDWR, dict_flags) :
|
||||
dict_open3(var_db_type, maps[n], O_RDWR, dict_flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform all requests.
|
||||
@@ -503,6 +510,8 @@ static int postmap_delete(const char *map_type, const char *map_name,
|
||||
DICT *dict;
|
||||
int status;
|
||||
|
||||
if (strcmp(map_type, DICT_TYPE_PROXY) == 0)
|
||||
msg_fatal("can't delete map entries via the proxy service");
|
||||
dict = dict_open3(map_type, map_name, O_RDWR, dict_flags);
|
||||
status = dict_del(dict, key);
|
||||
dict_close(dict);
|
||||
@@ -519,6 +528,8 @@ 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)
|
||||
|
@@ -6,9 +6,10 @@
|
||||
/* SYNOPSIS
|
||||
/* \fBproxymap\fR [generic Postfix daemon options]
|
||||
/* DESCRIPTION
|
||||
/* The \fBproxymap\fR(8) server provides read-only table
|
||||
/* lookup service to Postfix processes. The purpose
|
||||
/* of the service is:
|
||||
/* The \fBproxymap\fR(8) server provides read-only or read-write
|
||||
/* table lookup service to Postfix processes. These services are
|
||||
/* implemented with distinct service names: \fBproxymap\fR and
|
||||
/* \fBproxywrite\fR, respectively. The purpose of these services is:
|
||||
/* .IP \(bu
|
||||
/* To overcome chroot restrictions. For example, a chrooted SMTP
|
||||
/* server needs access to the system passwd file in order to
|
||||
@@ -33,6 +34,10 @@
|
||||
/* .sp
|
||||
/* The total number of connections is limited by the number of
|
||||
/* proxymap server processes.
|
||||
/* .IP \(bu
|
||||
/* To provide single-updater functionality for lookup tables
|
||||
/* that do not reliably support multiple writers (i.e. all
|
||||
/* file-based tables).
|
||||
/* .PP
|
||||
/* The \fBproxymap\fR(8) server implements the following requests:
|
||||
/* .IP "\fBopen\fR \fImaptype:mapname flags\fR"
|
||||
@@ -42,11 +47,26 @@
|
||||
/* expression table).
|
||||
/* .IP "\fBlookup\fR \fImaptype:mapname flags key\fR"
|
||||
/* Look up the data stored under the requested key.
|
||||
/* The reply is the request completion status code (below) and
|
||||
/* The reply is the request completion status code and
|
||||
/* the lookup result value.
|
||||
/* The \fImaptype:mapname\fR and \fIflags\fR are the same
|
||||
/* as with the \fBopen\fR request.
|
||||
/* .IP "\fBupdate\fR \fImaptype:mapname flags key value\fR"
|
||||
/* Update the data stored under the requested key.
|
||||
/* The reply is the request completion status code.
|
||||
/* The \fImaptype:mapname\fR and \fIflags\fR are the same
|
||||
/* as with the \fBopen\fR request.
|
||||
/* .sp
|
||||
/* To implement single-updater maps, specify a process limit
|
||||
/* of 1 in the master.cf file entry for the proxywrite service.
|
||||
/* .sp
|
||||
/* This request is supported in Postfix 2.5 and later.
|
||||
/* .PP
|
||||
/* The request completion status is one of OK, RETRY, NOKEY
|
||||
/* (lookup failed because the key was not found), BAD (malformed
|
||||
/* request) or DENY (the table is not approved for proxy read
|
||||
/* or update access).
|
||||
/*
|
||||
/* There is no \fBclose\fR command, nor are tables implicitly closed
|
||||
/* when a client disconnects. The purpose is to share tables among
|
||||
/* multiple client processes.
|
||||
@@ -64,8 +84,9 @@
|
||||
/* SECURITY
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The \fBproxymap\fR(8) server opens only tables that are approved via the
|
||||
/* \fBproxy_read_maps\fR configuration parameter, does not talk to
|
||||
/* The \fBproxymap\fR(8) server opens only tables that are
|
||||
/* approved via the \fBproxy_read_maps\fR or \fBproxy_write_maps\fR
|
||||
/* configuration parameters, does not talk to
|
||||
/* users, and can run at fixed low privilege, chrooted or not.
|
||||
/* However, running the proxymap server chrooted severely limits
|
||||
/* usability, because it can open only chrooted tables.
|
||||
@@ -84,6 +105,15 @@
|
||||
/* The \fBproxymap\fR(8) server provides service to multiple clients,
|
||||
/* and must therefore not be used for tables that have high-latency
|
||||
/* lookups.
|
||||
/*
|
||||
/* The \fBproxymap\fR(8) read-write service does not explicitly
|
||||
/* close lookup tables (even if it did, this could not be relied on,
|
||||
/* because the process may be terminated between table updates).
|
||||
/* The read-write service should therefore not be used with tables that
|
||||
/* leave persistent storage in an inconsistent state between
|
||||
/* updates (for example, CDB). Tables that support "sync on
|
||||
/* update" should be safe (for example, Berkeley DB) as should
|
||||
/* tables that are implemented by a real DBMS.
|
||||
/* CONFIGURATION PARAMETERS
|
||||
/* .ad
|
||||
/* .fi
|
||||
@@ -114,7 +144,13 @@
|
||||
/* .IP "\fBprocess_name (read-only)\fR"
|
||||
/* The process name of a Postfix command or daemon process.
|
||||
/* .IP "\fBproxy_read_maps (see 'postconf -d' output)\fR"
|
||||
/* The lookup tables that the \fBproxymap\fR(8) server is allowed to access.
|
||||
/* The lookup tables that the \fBproxymap\fR(8) server is allowed to
|
||||
/* access for the read-only service.
|
||||
/* .PP
|
||||
/* Available in Postfix 2.5 and later:
|
||||
/* .IP "\fBproxy_write_maps (see 'postconf -d' output)\fR"
|
||||
/* The lookup tables that the \fBproxymap\fR(8) server is allowed to
|
||||
/* access for the read-write service.
|
||||
/* SEE ALSO
|
||||
/* postconf(5), configuration parameters
|
||||
/* master(5), generic daemon options
|
||||
@@ -189,11 +225,12 @@ char *var_rcpt_canon_maps;
|
||||
char *var_relocated_maps;
|
||||
char *var_transport_maps;
|
||||
char *var_proxy_read_maps;
|
||||
char *var_proxy_write_maps;
|
||||
|
||||
/*
|
||||
* The pre-approved, pre-parsed list of maps.
|
||||
*/
|
||||
static HTABLE *proxy_read_maps;
|
||||
static HTABLE *proxy_auth_maps;
|
||||
|
||||
/*
|
||||
* Shared and static to reduce memory allocation overhead.
|
||||
@@ -201,8 +238,14 @@ static HTABLE *proxy_read_maps;
|
||||
static VSTRING *request;
|
||||
static VSTRING *request_map;
|
||||
static VSTRING *request_key;
|
||||
static VSTRING *request_value;
|
||||
static VSTRING *map_type_name_flags;
|
||||
|
||||
/*
|
||||
* Are we a proxy writer or not?
|
||||
*/
|
||||
static int proxy_writer;
|
||||
|
||||
/*
|
||||
* Silly little macros.
|
||||
*/
|
||||
@@ -219,6 +262,7 @@ static DICT *proxy_map_find(const char *map_type_name, int request_flags,
|
||||
#define PROXY_COLON DICT_TYPE_PROXY ":"
|
||||
#define PROXY_COLON_LEN (sizeof(PROXY_COLON) - 1)
|
||||
#define READ_OPEN_FLAGS O_RDONLY
|
||||
#define WRITE_OPEN_FLAGS (O_RDWR | O_CREAT)
|
||||
|
||||
/*
|
||||
* Canonicalize the map name. If the map is not on the approved list,
|
||||
@@ -230,11 +274,13 @@ static DICT *proxy_map_find(const char *map_type_name, int request_flags,
|
||||
map_type_name += PROXY_COLON_LEN;
|
||||
if (strchr(map_type_name, ':') == 0)
|
||||
PROXY_MAP_FIND_ERROR_RETURN(PROXY_STAT_BAD);
|
||||
if (htable_locate(proxy_read_maps, map_type_name) == 0) {
|
||||
if (htable_locate(proxy_auth_maps, map_type_name) == 0) {
|
||||
msg_warn("request for unapproved table: \"%s\"", map_type_name);
|
||||
msg_warn("to approve this table for %s access, list %s:%s in %s:%s",
|
||||
MAIL_SERVICE_PROXYMAP, DICT_TYPE_PROXY, map_type_name,
|
||||
MAIN_CONF_FILE, VAR_PROXY_READ_MAPS);
|
||||
proxy_writer == 0 ? "read-only" : "read-write",
|
||||
DICT_TYPE_PROXY, map_type_name, MAIN_CONF_FILE,
|
||||
proxy_writer == 0 ? VAR_PROXY_READ_MAPS :
|
||||
VAR_PROXY_WRITE_MAPS);
|
||||
PROXY_MAP_FIND_ERROR_RETURN(PROXY_STAT_DENY);
|
||||
}
|
||||
|
||||
@@ -243,13 +289,21 @@ static DICT *proxy_map_find(const char *map_type_name, int request_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_NP_INST_MASK));
|
||||
if ((dict = dict_handle(STR(map_type_name_flags))) == 0)
|
||||
dict = dict_open(map_type_name, READ_OPEN_FLAGS, request_flags);
|
||||
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");
|
||||
if (proxy_writer)
|
||||
dict->flags |= DICT_FLAG_SYNC_UPDATE;
|
||||
dict_register(STR(map_type_name_flags), dict);
|
||||
return (dict);
|
||||
}
|
||||
@@ -297,6 +351,46 @@ static void proxymap_lookup_service(VSTREAM *client_stream)
|
||||
ATTR_TYPE_END);
|
||||
}
|
||||
|
||||
/* proxymap_update_service - remote update service */
|
||||
|
||||
static void proxymap_update_service(VSTREAM *client_stream)
|
||||
{
|
||||
int request_flags;
|
||||
DICT *dict;
|
||||
int reply_status;
|
||||
|
||||
/*
|
||||
* Process the request.
|
||||
*/
|
||||
if (attr_scan(client_stream, ATTR_FLAG_STRICT,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_TABLE, request_map,
|
||||
ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &request_flags,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_KEY, request_key,
|
||||
ATTR_TYPE_STR, MAIL_ATTR_VALUE, request_value,
|
||||
ATTR_TYPE_END) != 4) {
|
||||
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,
|
||||
&reply_status)) == 0) {
|
||||
/* void */ ;
|
||||
} else {
|
||||
dict->flags = ((dict->flags & ~DICT_FLAG_RQST_MASK)
|
||||
| (request_flags & DICT_FLAG_RQST_MASK));
|
||||
dict_put(dict, STR(request_key), STR(request_value));
|
||||
reply_status = PROXY_STAT_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Respond to the client.
|
||||
*/
|
||||
attr_print(client_stream, ATTR_FLAG_NONE,
|
||||
ATTR_TYPE_INT, MAIL_ATTR_STATUS, reply_status,
|
||||
ATTR_TYPE_END);
|
||||
}
|
||||
|
||||
/* proxymap_open_service - open remote lookup table */
|
||||
|
||||
static void proxymap_open_service(VSTREAM *client_stream)
|
||||
@@ -355,6 +449,8 @@ static void proxymap_service(VSTREAM *client_stream, char *unused_service,
|
||||
ATTR_TYPE_END) == 1) {
|
||||
if (VSTREQ(request, PROXY_REQ_LOOKUP)) {
|
||||
proxymap_lookup_service(client_stream);
|
||||
} else if (VSTREQ(request, PROXY_REQ_UPDATE)) {
|
||||
proxymap_update_service(client_stream);
|
||||
} else if (VSTREQ(request, PROXY_REQ_OPEN)) {
|
||||
proxymap_open_service(client_stream);
|
||||
} else {
|
||||
@@ -381,26 +477,37 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
|
||||
|
||||
/* post_jail_init - initialization after privilege drop */
|
||||
|
||||
static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
static void post_jail_init(char *service_name, char **unused_argv)
|
||||
{
|
||||
const char *sep = ", \t\r\n";
|
||||
char *saved_filter;
|
||||
char *bp;
|
||||
char *type_name;
|
||||
|
||||
/*
|
||||
* Are we proxy writer?
|
||||
*/
|
||||
if (strcmp(service_name, MAIL_SERVICE_PROXYWRITE) == 0)
|
||||
proxy_writer = 1;
|
||||
else if (strcmp(service_name, MAIL_SERVICE_PROXYMAP) != 0)
|
||||
msg_fatal("service name must be one of %s or %s",
|
||||
MAIL_SERVICE_PROXYMAP, MAIL_SERVICE_PROXYMAP);
|
||||
|
||||
/*
|
||||
* Pre-allocate buffers.
|
||||
*/
|
||||
request = vstring_alloc(10);
|
||||
request_map = vstring_alloc(10);
|
||||
request_key = vstring_alloc(10);
|
||||
request_value = vstring_alloc(10);
|
||||
map_type_name_flags = vstring_alloc(10);
|
||||
|
||||
/*
|
||||
* Prepare the pre-approved list of proxied tables.
|
||||
*/
|
||||
saved_filter = bp = mystrdup(var_proxy_read_maps);
|
||||
proxy_read_maps = htable_create(13);
|
||||
saved_filter = bp = mystrdup(proxy_writer ? var_proxy_write_maps :
|
||||
var_proxy_read_maps);
|
||||
proxy_auth_maps = htable_create(13);
|
||||
while ((type_name = mystrtok(&bp, sep)) != 0) {
|
||||
if (strncmp(type_name, PROXY_COLON, PROXY_COLON_LEN))
|
||||
continue;
|
||||
@@ -408,8 +515,8 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
type_name += PROXY_COLON_LEN;
|
||||
} while (!strncmp(type_name, PROXY_COLON, PROXY_COLON_LEN));
|
||||
if (strchr(type_name, ':') != 0
|
||||
&& htable_locate(proxy_read_maps, type_name) == 0)
|
||||
(void) htable_enter(proxy_read_maps, type_name, (char *) 0);
|
||||
&& htable_locate(proxy_auth_maps, type_name) == 0)
|
||||
(void) htable_enter(proxy_auth_maps, type_name, (char *) 0);
|
||||
}
|
||||
myfree(saved_filter);
|
||||
|
||||
@@ -418,6 +525,13 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
||||
* time, so we don't have to do it another time.
|
||||
*/
|
||||
var_idle_limit = 1;
|
||||
|
||||
/*
|
||||
* Never, ever, get killed by a master signal, as that could corrupt a
|
||||
* persistent database when we're in the middle of an update.
|
||||
*/
|
||||
if (proxy_writer != 0)
|
||||
setsid();
|
||||
}
|
||||
|
||||
/* pre_accept - see if tables have changed */
|
||||
@@ -426,7 +540,7 @@ static void pre_accept(char *unused_name, char **unused_argv)
|
||||
{
|
||||
const char *table;
|
||||
|
||||
if ((table = dict_changed_name()) != 0) {
|
||||
if (proxy_writer == 0 && (table = dict_changed_name()) != 0) {
|
||||
msg_info("table %s has changed -- restarting", table);
|
||||
exit(0);
|
||||
}
|
||||
@@ -452,6 +566,7 @@ int main(int argc, char **argv)
|
||||
VAR_RELOCATED_MAPS, DEF_RELOCATED_MAPS, &var_relocated_maps, 0, 0,
|
||||
VAR_TRANSPORT_MAPS, DEF_TRANSPORT_MAPS, &var_transport_maps, 0, 0,
|
||||
VAR_PROXY_READ_MAPS, DEF_PROXY_READ_MAPS, &var_proxy_read_maps, 0, 0,
|
||||
VAR_PROXY_WRITE_MAPS, DEF_PROXY_WRITE_MAPS, &var_proxy_write_maps, 0, 0,
|
||||
0,
|
||||
};
|
||||
|
||||
@@ -464,5 +579,6 @@ int main(int argc, char **argv)
|
||||
MAIL_SERVER_STR_TABLE, str_table,
|
||||
MAIL_SERVER_POST_INIT, post_jail_init,
|
||||
MAIL_SERVER_PRE_ACCEPT, pre_accept,
|
||||
/* XXX MAIL_SERVER_SOLITARY if proxywrite */
|
||||
0);
|
||||
}
|
||||
|
@@ -306,7 +306,7 @@ void qmgr_queue_throttle(QMGR_QUEUE *queue, DSN *dsn)
|
||||
queue->fail_cohorts += 1.0 / queue->window;
|
||||
if (transport->fail_cohort_limit > 0
|
||||
&& queue->fail_cohorts >= transport->fail_cohort_limit)
|
||||
queue->window = 0;
|
||||
queue->window = QMGR_QUEUE_STAT_THROTTLED;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -95,7 +95,9 @@ extern DICT *dict_debug(DICT *);
|
||||
#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)
|
||||
#define DICT_FLAG_RQST_MASK DICT_FLAG_FOLD_ANY
|
||||
#define DICT_FLAG_RQST_MASK (DICT_FLAG_FOLD_ANY | DICT_FLAG_LOCK | \
|
||||
DICT_FLAG_DUP_REPLACE | DICT_FLAG_DUP_WARN | \
|
||||
DICT_FLAG_SYNC_UPDATE)
|
||||
#define DICT_FLAG_NP_INST_MASK ~(DICT_FLAG_IMPL_MASK | DICT_FLAG_RQST_MASK)
|
||||
#define DICT_FLAG_INST_MASK (DICT_FLAG_NP_INST_MASK | DICT_FLAG_PARANOID)
|
||||
|
||||
|
Reference in New Issue
Block a user