2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-24 19:08:27 +00:00

postfix-3.6-20200920

This commit is contained in:
Wietse Venema 2020-09-20 00:00:00 -05:00 committed by Viktor Dukhovni
parent c3f7b853c3
commit e4f3f9ea70
76 changed files with 1186 additions and 500 deletions

2
postfix/.indent.pro vendored
View File

@ -1,4 +1,4 @@
-TABOUNCE
-TABOUNCE_STATE
-TADDR_MATCH_LIST
-TADDR_PATTERN
-TALIAS_TOKEN

View File

@ -25057,6 +25057,8 @@ Apologies for any names omitted.
mantools/man2html, mantools/readme2html, proto/*_README.html,
proto/INSTALL.html, proto/postconf.html.prolog, html/index.html.
20200830
Refactor: moved the SASL mechanism filter code from the
Postfix SMTP client to a library module, so that it can be
reused in the Postfix SMTP server. Files: smtp/smtp_sasl_proto.c,
@ -25071,3 +25073,83 @@ Apologies for any names omitted.
wants to anounce EXTERNAL support for which Postfix support
does not exist. Files: smtpd/smtpd.[hc], smtpd_sasl_glue.[hc],
global/mail_params.h, proto/postconf.proto, mantools/postlink.
20200906
Cleanup: missing file. File: src/postqueue/.indent.pro.
Cleanup: uninitialized value in unit test code. File:
global/haproxy_srvr.c.
Cleanup: duplicate 'const' in argument declaration. File:
src/global/sasl_mech_filter.c.
20200906-18
Baseline is postfix-3.6-20200906.
Other debt: internal protocol identification. Each server
sends the name of the internal protocol that it implements,
and each client logs a warning if it receives the wrong
protocol name. With this, a client-server mismatch results
in a better error message. It is a good idea to "postfix
stop" before updating, or before backing out to an earlier
relase. To make this work consistently, a few internal
protocols were converted from "client speaks first" to
"server speaks first". Files: anvil/anvil.c, bounce/bounce.c,
cleanup/cleanup.c, flush/flush.c, global/abounce.c,
global/anvil_clnt.c, global/bounce.c, global/clnt_stream.c,
global/clnt_stream.h, global/defer.c, global/deliver_pass.c,
global/deliver_request.c, global/dict_proxy.c, global/flush_clnt.c,
global/mail_command_client.c, global/mail_proto.h,
global/mail_stream.c, global/mail_version.h, global/post_mail.c,
global/resolve_clnt.c, global/rewrite_clnt.c, global/scache_clnt.c,
global/trace.c, global/verify_clnt.c, local/forward.c,
master/event_server.c, master/mail_server.h, master/multi_server.c,
oqmgr/qmgr_deliver.c, pickup/pickup.c, postdrop/postdrop.c,
postqueue/postqueue.c, postscreen/postscreen_starttls.c,
proxymap/proxymap.c, qmgr/qmgr_deliver.c, scache/scache.c,
showq/showq.c, tls/tls_mgr.c, tls/tls_proxy_clnt.c,
tlsmgr/tlsmgr.c, tlsproxy/tlsproxy.c,
trivial-rewrite/trivial-rewrite.c, util/attr.h, util/attr_clnt.c,
util/attr_clnt.h, util/attr_print0.c, util/attr_print64.c,
util/attr_print_plain.c, util/attr_scan0.c, util/attr_scan64.c,
util/attr_scan_plain.c, util/auto_clnt.c, util/auto_clnt.h,
verify/verify.c.
Debt: during the conversion of some internal protocols to
"server speaks first", took the opportunity to improve how
event-driven client implementations handle a server that
is locked up. Files: global/abounce.c,
postscreen/postscreen_starttls.c.
20200919
Cleanup: eliminated a silly optimization for lazy clients
that read the "server speaks first" protocol announcement
after sending a client request. Files: src/anvil/anvil.c,
src/bounce/bounce.c, src/flush/flush.c, src/global/abounce.c,
src/global/anvil_clnt.c, src/global/deliver_pass.c,
src/global/deliver_request.c, src/global/dict_proxy.c,
src/global/mail_command_client.c, src/global/mail_stream.c,
src/global/resolve_clnt.c, src/global/rewrite_clnt.c,
src/global/scache_clnt.c, src/global/verify_clnt.c,
src/local/forward.c, src/oqmgr/qmgr_deliver.c, src/pickup/pickup.c,
src/postqueue/postqueue.c, src/postscreen/postscreen_starttls.c,
src/proxymap/proxymap.c, src/qmgr/qmgr_deliver.c,
src/scache/scache.c, src/showq/showq.c, src/tlsmgr/tlsmgr.c,
src/tlsproxy/tlsproxy.c, src/tls/tls_mgr.c,
src/tls/tls_proxy_clnt.c, src/trivial-rewrite/trivial-rewrite.c,
src/verify/verify.c.
Cleanup: factored out some duplicate showq client code.
File: postqueue/postqueue.c.
20200920
Cleanup: deleted the percentm module. It was obsoleted in
19971027 by the vbuf_print() string formatter for VSTREAM
and VSTRING objects. Files: util/percentm.[hc].
Cleanup: replaced hard-coded 'private' with named constant.
File: global/scache_clnt.c.

View File

@ -25,6 +25,22 @@ more recent Eclipse Public License 2.0. Recipients can choose to take
the software under the license of their choice. Those who are more
comfortable with the IPL can continue with that license.
Incompatible change with snapshot 20200920
==========================================
Internal protocols have changed. You need to "postfix stop" before
updating, or before backing out to an earlier release, otherwise
long-running daemons (pickup, qmgr, verify, tlsproxy, postscreen)
may fail to communicate with the rest of Postfix (warnings, timeouts).
The purpose of this change is to produce better error messages, for
example, when someone configures the discard daemon as a bounce
service in master.cf, or vice versa.
This change will break third-party code that implements a
Postfix-internal protocol such as qpsmtpd. Programs that depend on
Postfix internal details are not supported.
Incompatible change with snapshot 20200705
==========================================

View File

@ -1,5 +1,23 @@
Wish list:
Does tlsproxy terminate to soon after 'postfix reload'?
The documented order of relay/recipient restrictions differs
from the implementation. This may need a new compatibility
parameter. For example:
http://postfix.1071664.n5.nabble.com/Relay-attempt-questions-td103646.html
Hardening the half-dane behavior: some sites may rely on
current behavior which allows original MX domain name for
certificate matches. Requires a new (compatibility) parameter
setting?
multi_server applications could be migrated to event_server;
after accept(), they would have to set up their own read
event callback for handling requests.
Maybe expand %m to "application error" when errno == 0.
smtp_sasl_tls_security_options = noanonymous, and make
smtp_sasl_security_options default dependent on the
smtp_sasl_tls_security_options default (i.e. reverse the

View File

@ -162,8 +162,9 @@ CLEANUP(8) CLEANUP(8)
Postfix 2.6 the default protocol is 2.
<b><a href="postconf.5.html#milter_default_action">milter_default_action</a> (tempfail)</b>
The default action when a Milter (mail filter) application is
unavailable or mis-configured.
The default action when a Milter (mail filter) response is
unavailable (for example, bad Postfix configuration or Milter
failure).
<b><a href="postconf.5.html#milter_macro_daemon_name">milter_macro_daemon_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
The {daemon_name} macro value for Milter (mail filter) applica-

View File

@ -169,8 +169,8 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
explicit ".example.com" pattern.
<b><a href="postconf.5.html#relayhost">relayhost</a> (empty)</b>
The next-hop destination of non-local mail; overrides non-local
domains in recipient addresses.
The next-hop destination(s) for non-local mail; overrides
non-<a href="ADDRESS_CLASS_README.html#local_domain_class">local domains</a> in recipient addresses.
<b><a href="postconf.5.html#transport_maps">transport_maps</a> (empty)</b>
Optional lookup tables with mappings from recipient address to

View File

@ -164,8 +164,9 @@ The mail filter protocol version and optional protocol extensions
for communication with a Milter application; prior to Postfix 2.6
the default protocol is 2.
.IP "\fBmilter_default_action (tempfail)\fR"
The default action when a Milter (mail filter) application is
unavailable or mis\-configured.
The default action when a Milter (mail filter) response is
unavailable (for example, bad Postfix configuration or Milter
failure).
.IP "\fBmilter_macro_daemon_name ($myhostname)\fR"
The {daemon_name} macro value for Milter (mail filter) applications.
.IP "\fBmilter_macro_v ($mail_name $mail_version)\fR"

View File

@ -175,7 +175,7 @@ A list of Postfix features where the pattern "example.com" also
matches subdomains of example.com,
instead of requiring an explicit ".example.com" pattern.
.IP "\fBrelayhost (empty)\fR"
The next\-hop destination of non\-local mail; overrides non\-local
The next\-hop destination(s) for non\-local mail; overrides non\-local
domains in recipient addresses.
.IP "\fBtransport_maps (empty)\fR"
Optional lookup tables with mappings from recipient address to

View File

@ -1006,6 +1006,21 @@ static void post_jail_init(char *unused_name, char **unused_argv)
MAIL_VERSION_STAMP_DECLARE;
/* post_accept - announce our protocol */
static void post_accept(VSTREAM *stream, char *unused_name,
char **unused_argv, HTABLE *unused_table)
{
/*
* Announce the protocol.
*/
attr_print_plain(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_ANVIL),
ATTR_TYPE_END);
(void) vstream_fflush(stream);
}
/* main - pass control to the multi-threaded skeleton */
int main(int argc, char **argv)
@ -1024,6 +1039,7 @@ int main(int argc, char **argv)
multi_server_main(argc, argv, anvil_service,
CA_MAIL_SERVER_TIME_TABLE(time_table),
CA_MAIL_SERVER_POST_INIT(post_jail_init),
CA_MAIL_SERVER_POST_ACCEPT(post_accept),
CA_MAIL_SERVER_SOLITARY,
CA_MAIL_SERVER_PRE_DISCONN(anvil_service_done),
CA_MAIL_SERVER_EXIT(anvil_status_dump),

View File

@ -527,6 +527,14 @@ static void bounce_service(VSTREAM *client, char *service_name, char **argv)
if (mail_queue_name_ok(service_name) == 0)
msg_fatal("malformed service name: %s", service_name);
/*
* Announce the protocol.
*/
attr_print(client, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_BOUNCE),
ATTR_TYPE_END);
(void) vstream_fflush(client);
/*
* Read and validate the first parameter of the client request. Let the
* request-specific protocol routines take care of the remainder.

View File

@ -144,8 +144,9 @@
/* for communication with a Milter application; prior to Postfix 2.6
/* the default protocol is 2.
/* .IP "\fBmilter_default_action (tempfail)\fR"
/* The default action when a Milter (mail filter) application is
/* unavailable or mis-configured.
/* The default action when a Milter (mail filter) response is
/* unavailable (for example, bad Postfix configuration or Milter
/* failure).
/* .IP "\fBmilter_macro_daemon_name ($myhostname)\fR"
/* The {daemon_name} macro value for Milter (mail filter) applications.
/* .IP "\fBmilter_macro_v ($mail_name $mail_version)\fR"
@ -503,6 +504,7 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv)
* about the whole operation.
*/
attr_print(src, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, state->queue_id),
ATTR_TYPE_END);
if (attr_scan(src, ATTR_FLAG_STRICT,

View File

@ -699,6 +699,14 @@ static int flush_request_receive(VSTREAM *client_stream, VSTRING *request)
{
int count;
/*
* Announce the protocol.
*/
attr_print(client_stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_FLUSH),
ATTR_TYPE_END);
(void) vstream_fflush(client_stream);
/*
* Kluge: choose the protocol depending on the request size.
*/

View File

@ -169,6 +169,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -202,10 +207,11 @@ typedef struct {
int command; /* bounce request type */
int flags; /* bounce options */
char *id; /* queue ID for logging */
VSTRING *request; /* serialized request */
ABOUNCE_FN callback; /* application callback */
void *context; /* application context */
VSTREAM *fp; /* server I/O handle */
} ABOUNCE;
} ABOUNCE_STATE;
/*
* Encapsulate common code.
@ -215,11 +221,6 @@ typedef struct {
event_request_timer((callback), (context), (timeout)); \
} while (0)
#define ABOUNCE_EVENT_DISABLE(fd, callback, context) do { \
event_cancel_timer((callback), (context)); \
event_disable_readwrite(fd); \
} while (0)
/*
* If we set the reply timeout too short, then we make the problem worse by
* increasing overload. With 1000s timeout mail will keep flowing, but there
@ -228,11 +229,30 @@ typedef struct {
*/
#define ABOUNCE_TIMEOUT 1000
/*
* The initial buffer size for a serialized request.
*/
#define ABOUNCE_BUFSIZE VSTREAM_BUFSIZE
/*
* We share most of the verp and non-verp code paths.
*/
#define ABOUNCE_NO_VERP ((char *) 0)
/*
* SLMs.
*/
#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)
/* abounce_done - deliver status to application and clean up pseudo thread */
static void abounce_done(ABOUNCE *ap, int status)
static void abounce_done(ABOUNCE_STATE *ap, int status)
{
if (ap->fp) {
event_disable_readwrite(vstream_fileno(ap->fp));
(void) vstream_fclose(ap->fp);
}
if (status != 0 && (ap->flags & BOUNCE_FLAG_CLEAN) == 0)
msg_info("%s: status=deferred (%s failed)", ap->id,
ap->command == BOUNCE_CMD_FLUSH ? "bounce" :
@ -242,52 +262,102 @@ static void abounce_done(ABOUNCE *ap, int status)
"whatever");
ap->callback(status, ap->context);
myfree(ap->id);
vstring_free(ap->request);
myfree((void *) ap);
}
/* abounce_event - resume pseudo thread after server reply event */
/* abounce_receive - receive server reply */
static void abounce_event(int event, void *context)
static void abounce_receive(int event, void *context)
{
ABOUNCE *ap = (ABOUNCE *) context;
ABOUNCE_STATE *ap = (ABOUNCE_STATE *) context;
int status;
ABOUNCE_EVENT_DISABLE(vstream_fileno(ap->fp), abounce_event, context);
abounce_done(ap, (event != EVENT_TIME
if (event != EVENT_TIME)
event_cancel_timer(abounce_receive, context);
if (event == EVENT_READ
&& attr_scan(ap->fp, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
ATTR_TYPE_END) == 1) ? status : -1);
ATTR_TYPE_END) == 1) {
abounce_done(ap, status);
} else {
abounce_done(ap, -1);
}
}
/* abounce_request_verp - suspend pseudo thread until server reply event */
/* abounce_send - send the request and suspend until the server replies */
static void abounce_request_verp(const char *class, const char *service,
int command, int flags,
const char *queue, const char *id,
const char *encoding,
int smtputf8,
const char *sender,
const char *dsn_envid,
int dsn_ret,
const char *verp,
ABOUNCE_FN callback,
void *context)
static void abounce_send(int event, void *context)
{
ABOUNCE *ap;
ABOUNCE_STATE *ap = (ABOUNCE_STATE *) context;
/*
* Save pseudo thread state. Connect to the server. Send the request and
* suspend the pseudo thread until the server replies (or dies).
* Receive the server's protocol name announcement. At this point the
* server is ready to receive a request without blocking the sender. Send
* the request and suspend until the server replies (or dies).
*/
ap = (ABOUNCE *) mymalloc(sizeof(*ap));
if (event != EVENT_TIME)
event_cancel_timer(abounce_send, context);
non_blocking(vstream_fileno(ap->fp), BLOCKING);
if (event == EVENT_READ
&& attr_scan(ap->fp, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_BOUNCE),
ATTR_TYPE_END) == 0
&& vstream_fwrite(ap->fp, STR(ap->request),
LEN(ap->request)) == LEN(ap->request)
&& vstream_fflush(ap->fp) == 0) {
ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_receive,
(void *) ap, ABOUNCE_TIMEOUT);
} else {
abounce_done(ap, -1);
}
}
/* abounce_connect - connect and suspend until the server replies */
static void abounce_connect(const char *class, const char *service,
int command, int flags,
const char *queue, const char *id,
const char *encoding, int smtputf8,
const char *sender,
const char *dsn_envid, int dsn_ret,
const char *verp, ABOUNCE_FN callback,
void *context)
{
ABOUNCE_STATE *ap;
/*
* Save pseudo thread state. Connect to the server. Prior to Postfix 3.6
* the asynchronous bounce flush/warn client called mail_connect_wait()
* which sleeps and retries several times before terminating with a fatal
* error. This block-and-sleep behavior was not consistent with a) the
* rest of the code in this module, and with b) the synchronous bounce
* client which gives up immediately. It should be safe to give up
* immediately because that leaves the bounce/defer/trace logs in the
* queue. In particular, this should not increase the simultaneous number
* of asynchronous bounce/defer/trace flush/warn requests that are in
* flight.
*/
ap = (ABOUNCE_STATE *) mymalloc(sizeof(*ap));
ap->command = command;
ap->flags = flags;
ap->id = mystrdup(id);
ap->request = vstring_alloc(ABOUNCE_BUFSIZE);
ap->callback = callback;
ap->context = context;
ap->fp = mail_connect_wait(class, service);
ap->fp = mail_connect(class, service, NON_BLOCKING);
if (attr_print(ap->fp, ATTR_FLAG_NONE,
/*
* Format the request now, so that we don't have to save a lot of
* arguments now and format the request later.
*/
if (ap->fp != 0) {
/* Note: all code paths must terminate or enable I/O events. */
VSTREAM *mp = vstream_memopen(ap->request, O_WRONLY);
if (attr_print(mp, ATTR_FLAG_MORE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, command),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
@ -297,10 +367,20 @@ static void abounce_request_verp(const char *class, const char *service,
SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid),
SEND_ATTR_INT(MAIL_ATTR_DSN_RET, dsn_ret),
ATTR_TYPE_END) != 0
|| (verp != 0
&& attr_print(mp, ATTR_FLAG_MORE,
SEND_ATTR_STR(MAIL_ATTR_VERPDL, verp),
ATTR_TYPE_END) == 0
&& vstream_fflush(ap->fp) == 0) {
ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event,
ATTR_TYPE_END) != 0)
|| attr_print(mp, ATTR_FLAG_NONE,
ATTR_TYPE_END) != 0
|| vstream_fclose(mp) != 0)
msg_panic("abounce_connect: write request to memory stream: %m");
/*
* Suspend until the server replies (or dies).
*/
ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_send,
(void *) ap, ABOUNCE_TIMEOUT);
} else {
abounce_done(ap, -1);
@ -316,7 +396,7 @@ void abounce_flush_verp(int flags, const char *queue, const char *id,
ABOUNCE_FN callback,
void *context)
{
abounce_request_verp(MAIL_CLASS_PRIVATE, var_bounce_service,
abounce_connect(MAIL_CLASS_PRIVATE, var_bounce_service,
BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8,
sender, dsn_envid, dsn_ret, verp, callback, context);
}
@ -330,54 +410,11 @@ void adefer_flush_verp(int flags, const char *queue, const char *id,
ABOUNCE_FN callback, void *context)
{
flags |= BOUNCE_FLAG_DELRCPT;
abounce_request_verp(MAIL_CLASS_PRIVATE, var_defer_service,
abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service,
BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8,
sender, dsn_envid, dsn_ret, verp, callback, context);
}
/* abounce_request - suspend pseudo thread until server reply event */
static void abounce_request(const char *class, const char *service,
int command, int flags,
const char *queue, const char *id,
const char *encoding, int smtputf8,
const char *sender,
const char *dsn_envid, int dsn_ret,
ABOUNCE_FN callback, void *context)
{
ABOUNCE *ap;
/*
* Save pseudo thread state. Connect to the server. Send the request and
* suspend the pseudo thread until the server replies (or dies).
*/
ap = (ABOUNCE *) mymalloc(sizeof(*ap));
ap->command = command;
ap->flags = flags;
ap->id = mystrdup(id);
ap->callback = callback;
ap->context = context;
ap->fp = mail_connect_wait(class, service);
if (attr_print(ap->fp, ATTR_FLAG_NONE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, command),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
SEND_ATTR_STR(MAIL_ATTR_ENCODING, encoding),
SEND_ATTR_INT(MAIL_ATTR_SMTPUTF8, smtputf8),
SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
SEND_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid),
SEND_ATTR_INT(MAIL_ATTR_DSN_RET, dsn_ret),
ATTR_TYPE_END) == 0
&& vstream_fflush(ap->fp) == 0) {
ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event,
(void *) ap, ABOUNCE_TIMEOUT);
} else {
abounce_done(ap, -1);
}
}
/* abounce_flush - asynchronous bounce flush */
void abounce_flush(int flags, const char *queue, const char *id,
@ -386,9 +423,9 @@ void abounce_flush(int flags, const char *queue, const char *id,
int dsn_ret, ABOUNCE_FN callback,
void *context)
{
abounce_request(MAIL_CLASS_PRIVATE, var_bounce_service, BOUNCE_CMD_FLUSH,
abounce_connect(MAIL_CLASS_PRIVATE, var_bounce_service, BOUNCE_CMD_FLUSH,
flags, queue, id, encoding, smtputf8, sender, dsn_envid,
dsn_ret, callback, context);
dsn_ret, ABOUNCE_NO_VERP, callback, context);
}
/* adefer_flush - asynchronous defer flush */
@ -399,9 +436,9 @@ void adefer_flush(int flags, const char *queue, const char *id,
int dsn_ret, ABOUNCE_FN callback, void *context)
{
flags |= BOUNCE_FLAG_DELRCPT;
abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_FLUSH,
abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_FLUSH,
flags, queue, id, encoding, smtputf8, sender, dsn_envid,
dsn_ret, callback, context);
dsn_ret, ABOUNCE_NO_VERP, callback, context);
}
/* adefer_warn - send copy of defer log to sender as warning bounce */
@ -411,9 +448,9 @@ void adefer_warn(int flags, const char *queue, const char *id,
const char *sender, const char *dsn_envid,
int dsn_ret, ABOUNCE_FN callback, void *context)
{
abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_WARN,
abounce_connect(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_WARN,
flags, queue, id, encoding, smtputf8, sender, dsn_envid,
dsn_ret, callback, context);
dsn_ret, ABOUNCE_NO_VERP, callback, context);
}
/* atrace_flush - asynchronous trace flush */
@ -423,7 +460,7 @@ void atrace_flush(int flags, const char *queue, const char *id,
const char *sender, const char *dsn_envid,
int dsn_ret, ABOUNCE_FN callback, void *context)
{
abounce_request(MAIL_CLASS_PRIVATE, var_trace_service, BOUNCE_CMD_TRACE,
abounce_connect(MAIL_CLASS_PRIVATE, var_trace_service, BOUNCE_CMD_TRACE,
flags, queue, id, encoding, smtputf8, sender, dsn_envid,
dsn_ret, callback, context);
dsn_ret, ABOUNCE_NO_VERP, callback, context);
}

View File

@ -170,6 +170,15 @@
#define ANVIL_IDENT(service, addr) \
printable(concatenate(service, ":", addr, (char *) 0), '?')
/* anvil_clnt_handshake - receive server protocol announcement */
static int anvil_clnt_handshake(VSTREAM *stream)
{
return (attr_scan_plain(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_ANVIL),
ATTR_TYPE_END));
}
/* anvil_clnt_create - instantiate connection rate service client */
ANVIL_CLNT *anvil_clnt_create(void)
@ -186,6 +195,9 @@ ANVIL_CLNT *anvil_clnt_create(void)
#else
anvil_clnt = attr_clnt_create(var_anvil_service, var_ipc_timeout, 0, 0);
#endif
attr_clnt_control(anvil_clnt,
ATTR_CLNT_CTL_HANDSHAKE, anvil_clnt_handshake,
ATTR_CLNT_CTL_END);
return ((ANVIL_CLNT *) anvil_clnt);
}

View File

@ -186,6 +186,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -310,6 +315,7 @@ int bounce_append_intern(int flags, const char *id, MSG_STATS *stats,
if (mail_command_client(MAIL_CLASS_PRIVATE, var_soft_bounce ?
var_defer_service : var_bounce_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
@ -353,6 +359,7 @@ int bounce_flush(int flags, const char *queue, const char *id,
if (var_soft_bounce)
return (-1);
if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
@ -387,6 +394,7 @@ int bounce_flush_verp(int flags, const char *queue, const char *id,
if (var_soft_bounce)
return (-1);
if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_VERP),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
@ -494,6 +502,7 @@ int bounce_one_intern(int flags, const char *queue, const char *id,
my_dsn.action = "failed";
if (mail_command_client(MAIL_CLASS_PRIVATE, var_bounce_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_ONE),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),

View File

@ -6,11 +6,15 @@
/* SYNOPSIS
/* #include <clnt_stream.h>
/*
/* CLNT_STREAM *clnt_stream_create(class, service, timeout, ttl)
/* typedef void (*CLNT_STREAM_HANDSHAKE_FN)(VSTREAM *)
/*
/* CLNT_STREAM *clnt_stream_create(class, service, timeout, ttl,
/* handshake)
/* const char *class;
/* const char *service;
/* int timeout;
/* int ttl;
/* CLNT_STREAM_HANDSHAKE_FN *handshake;
/*
/* VSTREAM *clnt_stream_access(clnt_stream)
/* CLNT_STREAM *clnt_stream;
@ -33,6 +37,8 @@
/*
/* clnt_stream_access() returns an open stream to the service specified
/* to clnt_stream_create(). The stream instance may change between calls.
/* This function returns null when the handshake function returned an
/* error.
/*
/* clnt_stream_recover() recovers from a server-initiated disconnect
/* that happened in the middle of an I/O operation.
@ -49,6 +55,10 @@
/* Idle time after which the client disconnects.
/* .IP ttl
/* Upper bound on the time that a connection is allowed to persist.
/* .IP handshake
/* Null pointer, or pointer to function that will be called
/* at the start of a new connection and that returns 0 in case
/* of success.
/* DIAGNOSTICS
/* Warnings: communication failure. Fatal error: mail system is down,
/* out of memory.
@ -63,6 +73,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -93,6 +108,7 @@ struct CLNT_STREAM {
VSTREAM *vstream; /* buffered I/O */
int timeout; /* time before client disconnect */
int ttl; /* time before client disconnect */
CLNT_STREAM_HANDSHAKE_FN handshake;
char *class; /* server class */
char *service; /* server name */
};
@ -205,6 +221,7 @@ void clnt_stream_recover(CLNT_STREAM *clnt_stream)
VSTREAM *clnt_stream_access(CLNT_STREAM *clnt_stream)
{
CLNT_STREAM_HANDSHAKE_FN handshake;
/*
* Open a stream or restart the idle timer.
@ -213,20 +230,26 @@ VSTREAM *clnt_stream_access(CLNT_STREAM *clnt_stream)
*/
if (clnt_stream->vstream == 0) {
clnt_stream_open(clnt_stream);
handshake = clnt_stream->handshake;
} else if (readable(vstream_fileno(clnt_stream->vstream))) {
clnt_stream_close(clnt_stream);
clnt_stream_open(clnt_stream);
handshake = clnt_stream->handshake;
} else {
event_request_timer(clnt_stream_event, (void *) clnt_stream,
clnt_stream->timeout);
handshake = 0;
}
if (handshake != 0 && handshake(clnt_stream->vstream) != 0)
return (0);
return (clnt_stream->vstream);
}
/* clnt_stream_create - create client stream connection */
CLNT_STREAM *clnt_stream_create(const char *class, const char *service,
int timeout, int ttl)
int timeout, int ttl,
CLNT_STREAM_HANDSHAKE_FN handshake)
{
CLNT_STREAM *clnt_stream;
@ -237,6 +260,7 @@ CLNT_STREAM *clnt_stream_create(const char *class, const char *service,
clnt_stream->vstream = 0;
clnt_stream->timeout = timeout;
clnt_stream->ttl = ttl;
clnt_stream->handshake = handshake;
clnt_stream->class = mystrdup(class);
clnt_stream->service = mystrdup(service);
return (clnt_stream);

View File

@ -20,9 +20,12 @@
* External interface.
*/
typedef struct CLNT_STREAM CLNT_STREAM;
typedef int (*CLNT_STREAM_HANDSHAKE_FN)(VSTREAM *);
extern CLNT_STREAM *clnt_stream_create(const char *, const char *, int, int);
extern CLNT_STREAM *clnt_stream_create(const char *, const char *, int, int,
CLNT_STREAM_HANDSHAKE_FN);
extern VSTREAM *clnt_stream_access(CLNT_STREAM *);
extern const char *clnt_stream_path(CLNT_STREAM *);
extern void clnt_stream_recover(CLNT_STREAM *);
extern void clnt_stream_free(CLNT_STREAM *);
@ -35,6 +38,11 @@ extern void clnt_stream_free(CLNT_STREAM *);
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
#endif

View File

@ -153,6 +153,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -257,6 +262,7 @@ int defer_append_intern(int flags, const char *id, MSG_STATS *stats,
my_dsn.action = "delayed";
if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
@ -301,6 +307,7 @@ int defer_flush(int flags, const char *queue, const char *id,
flags |= BOUNCE_FLAG_DELRCPT;
if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),
@ -325,6 +332,7 @@ int defer_warn(int flags, const char *queue, const char *id,
const char *sender, const char *envid, int dsn_ret)
{
if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_WARN),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),

View File

@ -49,6 +49,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -79,15 +84,13 @@
static int deliver_pass_initial_reply(VSTREAM *stream)
{
int stat;
if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat),
ATTR_TYPE_END) != 1) {
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
ATTR_TYPE_END) != 0) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
stat = -1;
return (-1);
}
return (stat);
return (0);
}
/* deliver_pass_send_request - send delivery request to delivery process */

View File

@ -92,6 +92,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -135,13 +140,13 @@ static int deliver_request_initial(VSTREAM *stream)
* delivery request; otherwise the queue manager could block in write().
*/
if (msg_verbose)
msg_info("deliver_request_initial: send initial status");
msg_info("deliver_request_initial: send initial response");
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_INT(MAIL_ATTR_STATUS, 0),
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
ATTR_TYPE_END);
if ((err = vstream_fflush(stream)) != 0)
if (msg_verbose)
msg_warn("send initial status: %m");
msg_warn("send initial response: %m");
return (err);
}

View File

@ -41,6 +41,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -89,6 +94,15 @@ typedef struct {
static CLNT_STREAM *proxymap_stream; /* read-only maps */
static CLNT_STREAM *proxywrite_stream; /* read-write maps */
/* dict_proxy_handshake - receive server protocol announcement */
static int dict_proxy_handshake(VSTREAM *stream)
{
return (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_PROXYMAP),
ATTR_TYPE_END));
}
/* dict_proxy_sequence - find first/next entry */
static int dict_proxy_sequence(DICT *dict, int function,
@ -118,7 +132,8 @@ static int dict_proxy_sequence(DICT *dict, int function,
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_SEQUENCE),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
@ -131,7 +146,7 @@ static int dict_proxy_sequence(DICT *dict, int function,
RECV_ATTR_STR(MAIL_ATTR_VALUE, dict_proxy->result),
ATTR_TYPE_END) != 3) {
if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
if (msg_verbose)
msg_info("%s: table=%s flags=%s func=%d -> status=%d key=%s val=%s",
@ -196,7 +211,8 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key)
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_LOOKUP),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
@ -208,7 +224,7 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key)
RECV_ATTR_STR(MAIL_ATTR_VALUE, dict_proxy->result),
ATTR_TYPE_END) != 2) {
if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno != ENOENT))
msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
if (msg_verbose)
msg_info("%s: table=%s flags=%s key=%s -> status=%d result=%s",
@ -266,7 +282,8 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value)
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_UPDATE),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
@ -278,7 +295,7 @@ static int dict_proxy_update(DICT *dict, const char *key, const char *value)
RECV_ATTR_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));
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
if (msg_verbose)
msg_info("%s: table=%s flags=%s key=%s value=%s -> status=%d",
@ -335,7 +352,8 @@ static int dict_proxy_delete(DICT *dict, const char *key)
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_DELETE),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict->name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, request_flags),
@ -347,7 +365,7 @@ static int dict_proxy_delete(DICT *dict, const char *key)
ATTR_TYPE_END) != 1) {
if (msg_verbose || count > 1 || (errno && errno != EPIPE && errno !=
ENOENT))
msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
if (msg_verbose)
msg_info("%s: table=%s flags=%s key=%s -> status=%d",
@ -443,7 +461,8 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
prefix = kludge = concatenate(var_queue_dir, "/",
MAIL_CLASS_PRIVATE, (char *) 0);
*pstream = clnt_stream_create(prefix, service, var_ipc_idle_limit,
var_ipc_ttl_limit);
var_ipc_ttl_limit,
dict_proxy_handshake);
if (kludge)
myfree(kludge);
myfree(relative_path);
@ -473,7 +492,8 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
for (;;) {
stream = clnt_stream_access(dict_proxy->clnt);
errno = 0;
if (attr_print(stream, ATTR_FLAG_NONE,
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, PROXY_REQ_OPEN),
SEND_ATTR_STR(MAIL_ATTR_TABLE, dict_proxy->dict.name),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, dict_proxy->inst_flags),
@ -484,7 +504,7 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
RECV_ATTR_INT(MAIL_ATTR_FLAGS, &server_flags),
ATTR_TYPE_END) != 2) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
msg_warn("%s: service %s: %m", VSTREAM_PATH(stream), myname);
msg_warn("%s: service %s: %m", myname, dict_proxy->service);
} else {
if (msg_verbose)
msg_info("%s: connect to map=%s status=%d server_flags=%s",

View File

@ -71,6 +71,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -125,6 +130,7 @@ int flush_purge(void)
status = FLUSH_STAT_DENY;
else
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
MAIL_ATTR_PROTO_FLUSH,
SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_PURGE),
ATTR_TYPE_END);
@ -151,6 +157,7 @@ int flush_refresh(void)
status = FLUSH_STAT_DENY;
else
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
MAIL_ATTR_PROTO_FLUSH,
SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_REFRESH),
ATTR_TYPE_END);
@ -182,6 +189,7 @@ int flush_send_site(const char *site)
VAR_RELAY_DOMAINS "=$mydestination to flush "
"mail for domain \"%s\"", site);
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
MAIL_ATTR_PROTO_FLUSH,
SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_SEND_SITE),
SEND_ATTR_STR(MAIL_ATTR_SITE, site),
ATTR_TYPE_END);
@ -210,6 +218,7 @@ int flush_send_file(const char *queue_id)
* Require that the service is turned on.
*/
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
MAIL_ATTR_PROTO_FLUSH,
SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_SEND_FILE),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),
ATTR_TYPE_END);
@ -242,6 +251,7 @@ int flush_add(const char *site, const char *queue_id)
VAR_RELAY_DOMAINS "=$mydestination to update "
"fast-flush logfile for domain \"%s\"", site);
status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
MAIL_ATTR_PROTO_FLUSH,
SEND_ATTR_STR(MAIL_ATTR_REQ, FLUSH_REQ_ADD),
SEND_ATTR_STR(MAIL_ATTR_SITE, site),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),

View File

@ -403,7 +403,6 @@ static const char *haproxy_srvr_parse_v2_hdr(const char *str, ssize_t *str_len,
return ("unsupported network protocol");
}
/* For now, skip and ignore TLVs. */
*non_proxy = 0;
*str_len = PP2_HEADER_LEN + ntohs(hdr_v2->len);
return (0);
@ -434,6 +433,8 @@ const char *haproxy_srvr_parse(const char *str, ssize_t *str_len,
if (proto_info == 0)
proto_info = inet_proto_info();
*non_proxy = 0;
/*
* XXX We don't accept connections with the "UNKNOWN" protocol type,
* because those would sidestep address-based access control mechanisms.
@ -471,7 +472,6 @@ const char *haproxy_srvr_parse(const char *str, ssize_t *str_len,
}
myfree(saved_str);
*non_proxy = 0;
return (err);
}

View File

@ -6,9 +6,10 @@
/* SYNOPSIS
/* #include <mail_proto.h>
/*
/* int mail_command_client(class, name, type, attr, ...)
/* int mail_command_client(class, name, proto, type, attr, ...)
/* const char *class;
/* const char *name;
/* const char *proto;
/* int type;
/* const char *attr;
/* DESCRIPTION
@ -21,6 +22,8 @@
/* Service type: MAIL_CLASS_PUBLIC or MAIL_CLASS_PRIVATE
/* .IP name
/* Service name (master.cf).
/* .IP proto
/* The expected protocol name in the server announcement.
/* .IP "type, attr, ..."
/* Attribute information as defined in attr_print(3).
/* DIAGNOSTICS
@ -65,7 +68,8 @@
/* mail_command_client - single-command transaction with completion status */
int mail_command_client(const char *class, const char *name,...)
int mail_command_client(const char *class, const char *name,
const char *proto,...)
{
va_list ap;
VSTREAM *stream;
@ -82,14 +86,20 @@ int mail_command_client(const char *class, const char *name,...)
msg_warn("connect to %s/%s: %m", class, name);
return (-1);
}
va_start(ap, name);
status = attr_vprint(stream, ATTR_FLAG_NONE, ap);
va_end(ap);
if (status != 0) {
if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, proto),
ATTR_TYPE_END) != 0) {
msg_warn("read %s: %m", VSTREAM_PATH(stream));
status = -1;
} else if (va_start(ap, proto),
(status = attr_vprint(stream, ATTR_FLAG_NONE, ap)),
va_end(ap),
(status != 0)) {
msg_warn("write %s: %m", VSTREAM_PATH(stream));
status = -1;
} else if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status), 0) != 1) {
RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
ATTR_TYPE_END) != 1) {
msg_warn("write/read %s: %m", VSTREAM_PATH(stream));
status = -1;
}

View File

@ -114,11 +114,32 @@
*/
extern VSTREAM *mail_connect(const char *, const char *, int);
extern VSTREAM *mail_connect_wait(const char *, const char *);
extern int mail_command_client(const char *, const char *,...);
extern int mail_command_client(const char *, const char *, const char *,...);
extern int mail_command_server(VSTREAM *,...);
extern int mail_trigger(const char *, const char *, const char *, ssize_t);
extern char *mail_pathname(const char *, const char *);
/*
* Each Postfix internal service identifies the protocol that it intends to
* use. On the receiver end, this information does not contribute to the
* reported number of received attributes (it is a constant).
*/
#define MAIL_ATTR_PROTO "protocol"
#define MAIL_ATTR_PROTO_ANVIL "anvil_protocol"
#define MAIL_ATTR_PROTO_BOUNCE "delivery_status_protocol"
#define MAIL_ATTR_PROTO_CLEANUP "cleanup_protocol"
#define MAIL_ATTR_PROTO_DELIVER "delivery_request_protocol"
#define MAIL_ATTR_PROTO_FLUSH "queue_flush_protocol"
#define MAIL_ATTR_PROTO_POSTDROP "postdrop_protocol"
#define MAIL_ATTR_PROTO_PROXYMAP "proxymap_protocol"
#define MAIL_ATTR_PROTO_SCACHE "connection_cache_protocol"
#define MAIL_ATTR_PROTO_SHOWQ "mail_queue_list_protocol"
#define MAIL_ATTR_PROTO_TLSMGR "tlsmgr_protocol"
#define MAIL_ATTR_PROTO_TLSPROXY "tlsproxy_protocol"
#define MAIL_ATTR_PROTO_TRIVIAL "trivial_rewrite_protocol"
#define MAIL_ATTR_PROTO_VERIFY "address_verification_prrotocol"
/*
* Attribute names.
*/

View File

@ -105,6 +105,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -440,7 +445,8 @@ MAIL_STREAM *mail_stream_service(const char *class, const char *name)
id_buf = vstring_alloc(10);
stream = mail_connect_wait(class, name);
if (attr_scan(stream, ATTR_FLAG_MISSING,
if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id_buf), 0) != 1) {
vstream_fclose(stream);
return (0);
@ -492,7 +498,8 @@ MAIL_STREAM *mail_stream_command(const char *command)
CA_VSTREAM_CTL_PATH(command),
CA_VSTREAM_CTL_END);
if (attr_scan(stream, ATTR_FLAG_MISSING,
if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_POSTDROP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id_buf), 0) != 1) {
if ((status = vstream_pclose(stream)) != 0)
msg_warn("command \"%s\" exited with status %d", command, status);

View File

@ -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 "20200830"
#define MAIL_RELEASE_DATE "20200920"
#define MAIL_VERSION_NUMBER "3.6"
#ifdef SNAPSHOT

View File

@ -231,8 +231,18 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
date = mail_date(now.tv_sec);
/*
* XXX Don't flush buffers while sending the initial message records.
* That would cause deadlock between verify(8) and cleanup(8) servers.
* The comment in the next paragraph is likely obsolete. Fix 20030610
* changed the verify server to use asynchronous submission of mail
* probes, to avoid blocking the post_mail client for in_flow_delay
* seconds when the cleanup service receives email messages faster than
* they are delivered. Instead, the post_mail client waits until the
* cleanup server announces its availability to receive input. A similar
* change was made at the end of submission, to avoid blocking the
* post_mail client for up to trigger_timeout seconds when the cleanup
* server attempts to notify a queue manager that is overwhelmed.
*
* XXX Don't flush buffers while sending the initial message records. That
* would cause deadlock between verify(8) and cleanup(8) servers.
*/
vstream_control(stream, VSTREAM_CTL_BUFSIZE, 2 * VSTREAM_BUFSIZE,
VSTREAM_CTL_END);
@ -241,6 +251,7 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
* Negotiate with the cleanup service. Give up if we can't agree.
*/
if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, id),
ATTR_TYPE_END) != 1
|| attr_print(stream, ATTR_FLAG_NONE,

View File

@ -152,6 +152,15 @@ void resolve_clnt_init(RESOLVE_REPLY *reply)
reply->flags = 0;
}
/* resolve_clnt_handshake - receive server protocol announcement */
static int resolve_clnt_handshake(VSTREAM *stream)
{
return (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL),
ATTR_TYPE_END));
}
/* resolve_clnt - resolve address to (transport, next hop, recipient) */
void resolve_clnt(const char *class, const char *sender,
@ -219,13 +228,15 @@ void resolve_clnt(const char *class, const char *sender,
rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE,
var_rewrite_service,
var_ipc_idle_limit,
var_ipc_ttl_limit);
var_ipc_ttl_limit,
resolve_clnt_handshake);
for (;;) {
stream = clnt_stream_access(rewrite_clnt_stream);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, class),
SEND_ATTR_STR(MAIL_ATTR_SENDER, sender),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),

View File

@ -39,6 +39,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -77,6 +82,15 @@ static VSTRING *last_rule;
static VSTRING *last_addr;
static VSTRING *last_result;
/* rewrite_clnt_handshake - receive server protocol announcement */
static int rewrite_clnt_handshake(VSTREAM *stream)
{
return (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL),
ATTR_TYPE_END));
}
/* rewrite_clnt - rewrite address to (transport, next hop, recipient) */
VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
@ -127,13 +141,15 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE,
var_rewrite_service,
var_ipc_idle_limit,
var_ipc_ttl_limit);
var_ipc_ttl_limit,
rewrite_clnt_handshake);
for (;;) {
stream = clnt_stream_access(rewrite_clnt_stream);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, REWRITE_ADDR),
SEND_ATTR_STR(MAIL_ATTR_RULE, rule),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),

View File

@ -68,7 +68,7 @@
/* sasl_mech_filter - filter a SASL mechanism list */
const char *sasl_mech_filter(STRING_LIST *filter,
const const char *words)
const char *words)
{
const char myname[] = "sasl_mech_filter";
static VSTRING *buf;

View File

@ -41,6 +41,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -80,6 +85,15 @@ typedef struct {
#define SCACHE_MAX_TRIES 2
/* scache_clnt_handshake - receive server protocol announcement */
static int scache_clnt_handshake(VSTREAM *stream)
{
return (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SCACHE),
ATTR_TYPE_END));
}
/* scache_clnt_save_endp - save endpoint */
static void scache_clnt_save_endp(SCACHE *scache, int endp_ttl,
@ -414,8 +428,11 @@ SCACHE *scache_clnt_create(const char *server, int timeout,
sp->scache->size = scache_clnt_size;
sp->scache->free = scache_clnt_free;
service = concatenate("local:private/", server, (char *) 0);
service = concatenate("local:" MAIL_CLASS_PRIVATE "/", server, (char *) 0);
sp->auto_clnt = auto_clnt_create(service, timeout, idle_limit, ttl_limit);
auto_clnt_control(sp->auto_clnt,
AUTO_CLNT_CTL_HANDSHAKE, scache_clnt_handshake,
AUTO_CLNT_CTL_END);
myfree(service);
#ifdef CANT_WRITE_BEFORE_SENDING_FD

View File

@ -79,6 +79,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -121,6 +126,7 @@ int trace_append(int flags, const char *id, MSG_STATS *stats,
my_dsn.reason = vstring_str(why);
if (mail_command_client(MAIL_CLASS_PRIVATE, var_trace_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, id),
@ -145,6 +151,7 @@ int trace_flush(int flags, const char *queue, const char *id,
const char *dsn_envid, int dsn_ret)
{
if (mail_command_client(MAIL_CLASS_PRIVATE, var_trace_service,
MAIL_ATTR_PROTO_BOUNCE,
SEND_ATTR_INT(MAIL_ATTR_NREQ, BOUNCE_CMD_TRACE),
SEND_ATTR_INT(MAIL_ATTR_FLAGS, flags),
SEND_ATTR_STR(MAIL_ATTR_QUEUE, queue),

View File

@ -56,6 +56,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -80,6 +85,15 @@
CLNT_STREAM *vrfy_clnt;
/* verify_clnt_handshake - receive server protocol announcement */
static int verify_clnt_handshake(VSTREAM *stream)
{
return (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_VERIFY),
ATTR_TYPE_END));
}
/* verify_clnt_init - initialize */
static void verify_clnt_init(void)
@ -87,7 +101,8 @@ static void verify_clnt_init(void)
if (vrfy_clnt != 0)
msg_panic("verify_clnt_init: multiple initialization");
vrfy_clnt = clnt_stream_create(MAIL_CLASS_PRIVATE, var_verify_service,
var_ipc_idle_limit, var_ipc_ttl_limit);
var_ipc_idle_limit, var_ipc_ttl_limit,
verify_clnt_handshake);
}
/* verify_clnt_query - request address verification status */
@ -111,7 +126,8 @@ int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why)
stream = clnt_stream_access(vrfy_clnt);
errno = 0;
count += 1;
if (attr_print(stream, ATTR_FLAG_NONE,
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_QUERY),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
ATTR_TYPE_END) != 0
@ -153,7 +169,8 @@ int verify_clnt_update(const char *addr, int addr_status, const char *why)
for (;;) {
stream = clnt_stream_access(vrfy_clnt);
errno = 0;
if (attr_print(stream, ATTR_FLAG_NONE,
if (stream == 0
|| attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_REQ, VRFY_REQ_UPDATE),
SEND_ATTR_STR(MAIL_ATTR_ADDR, addr),
SEND_ATTR_INT(MAIL_ATTR_ADDR_STATUS, addr_status),

View File

@ -146,6 +146,7 @@ static FORWARD_INFO *forward_open(DELIVER_REQUEST *request, const char *sender)
}
close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC);
if (attr_scan(cleanup, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buffer),
ATTR_TYPE_END) != 1) {
vstream_fclose(cleanup);

View File

@ -273,7 +273,6 @@ static unsigned event_server_generation;
static void (*event_server_pre_disconn) (VSTREAM *, char *, char **);
static void (*event_server_slow_exit) (char *, char **);
static int event_server_watchdog = 1000;
static int event_server_saved_flags;
/* event_server_exit - normal termination */
@ -373,8 +372,7 @@ void event_server_disconnect(VSTREAM *stream)
static void event_server_execute(int unused_event, void *context)
{
VSTREAM *stream = (VSTREAM *) context;
HTABLE *attr = (vstream_flags(stream) == event_server_saved_flags ?
(HTABLE *) vstream_context(stream) : 0);
HTABLE *attr = (HTABLE *) vstream_context(stream);
if (event_server_lock != 0
&& myflock(vstream_fileno(event_server_lock), INTERNAL_LOCK,
@ -432,7 +430,6 @@ static void event_server_wakeup(int fd, HTABLE *attr)
CA_VSTREAM_CTL_END);
myfree(tmp);
timed_ipc_setup(stream);
event_server_saved_flags = vstream_flags(stream);
if (event_server_in_flow_delay && mail_flow_get(1) < 0)
event_request_timer(event_server_execute, (void *) stream,
var_in_flow_delay);

View File

@ -12,6 +12,7 @@
* Utility library.
*/
#include <vstream.h>
#include <htable.h>
/*
* Global library.
@ -45,11 +46,13 @@
#define MAIL_SERVER_SLOW_EXIT 21
#define MAIL_SERVER_BOUNCE_INIT 22
#define MAIL_SERVER_RETIRE_ME 23
#define MAIL_SERVER_POST_ACCEPT 24
typedef void (*MAIL_SERVER_INIT_FN) (char *, char **);
typedef int (*MAIL_SERVER_LOOP_FN) (char *, char **);
typedef void (*MAIL_SERVER_EXIT_FN) (char *, char **);
typedef void (*MAIL_SERVER_ACCEPT_FN) (char *, char **);
typedef void (*MAIL_SERVER_POST_ACCEPT_FN) (VSTREAM *, char *, char **, HTABLE *);
typedef void (*MAIL_SERVER_DISCONN_FN) (VSTREAM *, char *, char **);
typedef void (*MAIL_SERVER_SLOW_EXIT_FN) (char *, char **);
@ -67,6 +70,7 @@ typedef void (*MAIL_SERVER_SLOW_EXIT_FN) (char *, char **);
#define CA_MAIL_SERVER_LOOP(v) MAIL_SERVER_LOOP, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_LOOP_FN, (v))
#define CA_MAIL_SERVER_EXIT(v) MAIL_SERVER_EXIT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_EXIT_FN, (v))
#define CA_MAIL_SERVER_PRE_ACCEPT(v) MAIL_SERVER_PRE_ACCEPT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_ACCEPT_FN, (v))
#define CA_MAIL_SERVER_POST_ACCEPT(v) MAIL_SERVER_POST_ACCEPT, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_POST_ACCEPT_FN, (v))
#define CA_MAIL_SERVER_SOLITARY MAIL_SERVER_SOLITARY
#define CA_MAIL_SERVER_UNLIMITED MAIL_SERVER_UNLIMITED
#define CA_MAIL_SERVER_PRE_DISCONN(v) MAIL_SERVER_PRE_DISCONN, CHECK_VAL(MAIL_SERVER, MAIL_SERVER_DISCONN_FN, (v))
@ -83,6 +87,7 @@ CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_INIT_FN);
CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_EXIT_FN);
CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_DISCONN_FN);
CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_ACCEPT_FN);
CHECK_VAL_HELPER_DCL(MAIL_SERVER, MAIL_SERVER_POST_ACCEPT_FN);
CHECK_PTR_HELPER_DCL(MAIL_SERVER, int);
CHECK_PTR_HELPER_DCL(MAIL_SERVER, char);
CHECK_PPTR_HELPER_DCL(MAIL_SERVER, char);

View File

@ -35,9 +35,6 @@
/* function is run after the program has optionally dropped its
/* privileges. This function should not attempt to preserve state
/* across calls. The stream initial state is non-blocking mode.
/* Optional connection attributes are provided as a hash that
/* is attached as stream context. NOTE: the attributes are
/* destroyed after this function is called.
/* The service name argument corresponds to the service name in the
/* master.cf file.
/* The argv argument specifies command-line arguments left over
@ -114,6 +111,14 @@
/* Function to be executed prior to accepting a new connection.
/* .sp
/* Only the last instance of this parameter type is remembered.
/* .IP "CA_MAIL_SERVER_POST_ACCEPT(void *(VSTREAM *stream, char *service_name, char **argv, HTABLE *attr))"
/* Function to be executed after accepting a new connection.
/* The stream, service_name and argv argunents are the same
/* as with the "service" argument. The attr argument is null
/* or a pointer to a table with 'pass' connection attributes.
/* The table is destroyed after the function returns.
/* .sp
/* Only the last instance of this parameter type is remembered.
/* .IP "CA_MAIL_SERVER_PRE_DISCONN(VSTREAM *, char *service_name, char **argv)"
/* A pointer to a function that is called
/* by the multi_server_disconnect() function (see below).
@ -250,11 +255,11 @@ static char **multi_server_argv;
static void (*multi_server_accept) (int, void *);
static void (*multi_server_onexit) (char *, char **);
static void (*multi_server_pre_accept) (char *, char **);
static void (*multi_server_post_accept) (VSTREAM *, char *, char **, HTABLE *);
static VSTREAM *multi_server_lock;
static int multi_server_in_flow_delay;
static unsigned multi_server_generation;
static void (*multi_server_pre_disconn) (VSTREAM *, char *, char **);
static int multi_server_saved_flags;
/* multi_server_exit - normal termination */
@ -336,8 +341,6 @@ void multi_server_disconnect(VSTREAM *stream)
static void multi_server_execute(int unused_event, void *context)
{
VSTREAM *stream = (VSTREAM *) context;
HTABLE *attr = (vstream_flags(stream) == multi_server_saved_flags ?
(HTABLE *) vstream_context(stream) : 0);
if (multi_server_lock != 0
&& myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK,
@ -358,8 +361,6 @@ static void multi_server_execute(int unused_event, void *context)
} else {
multi_server_disconnect(stream);
}
if (attr)
htable_free(attr, myfree);
}
/* multi_server_enable_read - enable read events */
@ -404,16 +405,20 @@ static void multi_server_wakeup(int fd, HTABLE *attr)
tmp = concatenate(multi_server_name, " socket", (char *) 0);
vstream_control(stream,
CA_VSTREAM_CTL_PATH(tmp),
CA_VSTREAM_CTL_CONTEXT((void *) attr),
CA_VSTREAM_CTL_END);
myfree(tmp);
timed_ipc_setup(stream);
multi_server_saved_flags = vstream_flags(stream);
if (multi_server_in_flow_delay && mail_flow_get(1) < 0)
event_request_timer(multi_server_enable_read, (void *) stream,
var_in_flow_delay);
else
multi_server_enable_read(0, (void *) stream);
if (multi_server_post_accept)
multi_server_post_accept(stream, multi_server_name, multi_server_argv, attr);
else if (attr)
msg_warn("service ignores 'pass' connection attributes");
if (attr)
htable_free(attr, myfree);
}
/* multi_server_accept_local - accept client connection request */
@ -746,6 +751,9 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
case MAIL_SERVER_PRE_ACCEPT:
multi_server_pre_accept = va_arg(ap, MAIL_SERVER_ACCEPT_FN);
break;
case MAIL_SERVER_POST_ACCEPT:
multi_server_post_accept = va_arg(ap, MAIL_SERVER_POST_ACCEPT_FN);
break;
case MAIL_SERVER_PRE_DISCONN:
multi_server_pre_disconn = va_arg(ap, MAIL_SERVER_DISCONN_FN);
break;

View File

@ -109,12 +109,12 @@ static int qmgr_deliver_initial_reply(VSTREAM *stream)
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH);
} else if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat),
ATTR_TYPE_END) != 1) {
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
ATTR_TYPE_END) != 0) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH);
return (DELIVER_STAT_DEFER);
} else {
return (stat ? DELIVER_STAT_DEFER : 0);
return (0);
}
}

View File

@ -488,6 +488,7 @@ static int pickup_file(PICKUP_INFO *info)
cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service);
if (attr_scan(cleanup, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_CLEANUP),
RECV_ATTR_STR(MAIL_ATTR_QUEUEID, buf),
ATTR_TYPE_END) != 1
|| attr_print(cleanup, ATTR_FLAG_NONE,

View File

@ -9,8 +9,8 @@ OBJS = postconf.o postconf_builtin.o postconf_edit.o postconf_main.o \
postconf_lookup.o postconf_match.o postconf_print.o
HDRS = postconf.h
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS) -DLEGACY_DBMS_SUPPORT
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) -DLEGACY_DBMS_SUPPORT
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
TESTPROG=
MAKES = bool_table.h bool_vars.h int_table.h int_vars.h str_table.h \
str_vars.h time_table.h time_vars.h raw_table.h raw_vars.h \

View File

@ -381,6 +381,7 @@ int main(int argc, char **argv)
dst = mail_stream_file(MAIL_QUEUE_MAILDROP, MAIL_CLASS_PUBLIC,
var_pickup_service, 0444);
attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_POSTDROP),
SEND_ATTR_STR(MAIL_ATTR_QUEUEID, dst->id),
ATTR_TYPE_END);
vstream_fflush(VSTREAM_OUT);

View File

@ -61,14 +61,19 @@ depend: $(MAKES)
# do not edit below this line - it is generated by 'make depend'
postlogd.o: ../../include/check_arg.h
postlogd.o: ../../include/htable.h
postlogd.o: ../../include/logwriter.h
postlogd.o: ../../include/mail_conf.h
postlogd.o: ../../include/mail_params.h
postlogd.o: ../../include/mail_server.h
postlogd.o: ../../include/mail_task.h
postlogd.o: ../../include/mail_version.h
postlogd.o: ../../include/maillog_client.h
postlogd.o: ../../include/msg.h
postlogd.o: ../../include/msg_logger.h
postlogd.o: ../../include/stringops.h
postlogd.o: ../../include/sys_defs.h
postlogd.o: ../../include/vbuf.h
postlogd.o: ../../include/vstream.h
postlogd.o: ../../include/vstring.h
postlogd.o: postlogd.c

1
postfix/src/postqueue/.indent.pro vendored Symbolic link
View File

@ -0,0 +1 @@
../../.indent.pro

View File

@ -341,6 +341,26 @@ static const CONFIG_STR_TABLE str_table[] = {
0,
};
/* showq_client - run the appropriate showq protocol client */
static void showq_client(int mode, VSTREAM *showq)
{
if (attr_scan(showq, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SHOWQ),
ATTR_TYPE_END) != 0)
msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
switch (mode) {
case PQ_MODE_MAILQ_LIST:
showq_compat(showq);
break;
case PQ_MODE_JSON_LIST:
showq_json(showq);
break;
default:
msg_panic("show_queue: unknown mode %d", mode);
}
}
/* show_queue - show queue status */
static void show_queue(int mode)
@ -361,16 +381,7 @@ static void show_queue(int mode)
* Connect to the show queue service.
*/
if ((showq = mail_connect(MAIL_CLASS_PUBLIC, var_showq_service, BLOCKING)) != 0) {
switch (mode) {
case PQ_MODE_MAILQ_LIST:
showq_compat(showq);
break;
case PQ_MODE_JSON_LIST:
showq_json(showq);
break;
default:
msg_panic("show_queue: unknown mode %d", mode);
}
showq_client(mode, showq);
if (vstream_fclose(showq))
msg_warn("close: %m");
}
@ -407,23 +418,14 @@ static void show_queue(int mode)
CA_VSTREAM_POPEN_END)) == 0) {
stat = -1;
} else {
switch (mode) {
case PQ_MODE_MAILQ_LIST:
showq_compat(showq);
break;
case PQ_MODE_JSON_LIST:
showq_json(showq);
break;
default:
msg_panic("show_queue: unknown mode %d", mode);
}
showq_client(mode, showq);
stat = vstream_pclose(showq);
}
argv_free(argv);
myfree(showq_path);
if (stat != 0)
msg_fatal_status(stat < 0 ? EX_OSERR : EX_SOFTWARE,
"Error running %s", showq_path);
myfree(showq_path);
}
/*

View File

@ -88,6 +88,22 @@ typedef struct {
static char *psc_tlsp_service = 0;
/* Resume the dummy SMTP engine after an event handling error */
#define PSC_STARTTLS_EVENT_ERR_RESUME_RETURN() do { \
event_disable_readwrite(vstream_fileno(tlsproxy_stream)); \
PSC_STARTTLS_EVENT_RESUME_RETURN(starttls_state); \
} while (0);
/* Resume the dummy SMTP engine, possibly after swapping streams */
#define PSC_STARTTLS_EVENT_RESUME_RETURN(starttls_state) do { \
vstream_fclose(tlsproxy_stream); \
starttls_state->resume_event(event, (void *) smtp_state); \
myfree((void *) starttls_state); \
return; \
} while (0)
/* psc_starttls_finish - complete negotiation with TLS proxy */
static void psc_starttls_finish(int event, void *context)
@ -130,10 +146,11 @@ static void psc_starttls_finish(int event, void *context)
* The TLS proxy reports that the TLS engine is not available (due to
* configuration error, or other causes).
*/
event_disable_readwrite(vstream_fileno(tlsproxy_stream));
vstream_fclose(tlsproxy_stream);
msg_warn("%s receiving status from %s service",
event == EVENT_TIME ? "timeout" : "problem", psc_tlsp_service);
PSC_SEND_REPLY(smtp_state,
"454 4.7.0 TLS not available due to local problem\r\n");
PSC_STARTTLS_EVENT_ERR_RESUME_RETURN();
}
/*
@ -145,13 +162,10 @@ static void psc_starttls_finish(int event, void *context)
/*
* Some error: drop the TLS proxy stream.
*/
msg_warn("%s sending file handle to %s service",
event == EVENT_TIME ? "timeout" : "problem",
psc_tlsp_service);
event_disable_readwrite(vstream_fileno(tlsproxy_stream));
vstream_fclose(tlsproxy_stream);
msg_warn("problem sending file handle to %s service", psc_tlsp_service);
PSC_SEND_REPLY(smtp_state,
"454 4.7.0 TLS not available due to local problem\r\n");
PSC_STARTTLS_EVENT_ERR_RESUME_RETURN();
}
/*
@ -163,9 +177,10 @@ static void psc_starttls_finish(int event, void *context)
PSC_SEND_REPLY(smtp_state, "220 2.0.0 Ready to start TLS\r\n");
/*
* Replace our SMTP client stream by the TLS proxy stream. Once the
* TLS handshake is done, the TLS proxy will deliver plaintext SMTP
* commands to postscreen(8).
* Swap the SMTP client stream and the TLS proxy stream, and close
* the direct connection to the SMTP client. The TLS proxy will talk
* directly to the SMTP client, and once the TLS handshake is
* completed, the TLS proxy will talk plaintext to postscreen(8).
*
* Swap the file descriptors from under the VSTREAM so that we don't
* have to worry about loss of user-configurable VSTREAM attributes.
@ -174,15 +189,83 @@ static void psc_starttls_finish(int event, void *context)
vstream_control(smtp_state->smtp_client_stream,
CA_VSTREAM_CTL_SWAP_FD(tlsproxy_stream),
CA_VSTREAM_CTL_END);
vstream_fclose(tlsproxy_stream); /* direct-to-client stream! */
smtp_state->flags |= PSC_STATE_FLAG_USING_TLS;
PSC_STARTTLS_EVENT_RESUME_RETURN(starttls_state);
}
}
/* psc_starttls_first - start negotiation with TLS proxy */
static void psc_starttls_first(int event, void *context)
{
const char *myname = "psc_starttls_first";
PSC_STARTTLS *starttls_state = (PSC_STARTTLS *) context;
PSC_STATE *smtp_state = starttls_state->smtp_state;
VSTREAM *tlsproxy_stream = starttls_state->tlsproxy_stream;
static VSTRING *remote_endpt = 0;
if (msg_verbose)
msg_info("%s: receive server protocol on proxy socket %d"
" for smtp socket %d from [%s]:%s flags=%s",
myname, vstream_fileno(tlsproxy_stream),
vstream_fileno(smtp_state->smtp_client_stream),
smtp_state->smtp_client_addr, smtp_state->smtp_client_port,
psc_print_state_flags(smtp_state->flags, myname));
/*
* We leave read-event notification enabled on the postscreen to TLS
* proxy stream, to avoid two kqueue/epoll/etc. system calls: one here,
* and one when resuming the dummy SMTP engine.
*/
if (event != EVENT_TIME)
event_cancel_timer(psc_starttls_first, (void *) starttls_state);
/*
* Receive and verify the server protocol.
*/
if (event != EVENT_READ
|| attr_scan(tlsproxy_stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSPROXY),
ATTR_TYPE_END) != 0) {
msg_warn("%s receiving %s attribute from %s service: %m",
event == EVENT_TIME ? "timeout" : "problem",
MAIL_ATTR_PROTO, psc_tlsp_service);
PSC_SEND_REPLY(smtp_state,
"454 4.7.0 TLS not available due to local problem\r\n");
PSC_STARTTLS_EVENT_ERR_RESUME_RETURN();
}
/*
* Resume the postscreen(8) dummy SMTP engine and clean up.
* Send the data attributes now, and send the client file descriptor in a
* later transaction. We report all errors asynchronously, to avoid
* having to maintain multiple error delivery paths.
*
* XXX The formatted endpoint should be a state member. Then, we can
* simplify all the format strings throughout the program.
*/
starttls_state->resume_event(event, (void *) smtp_state);
myfree((void *) starttls_state);
if (remote_endpt == 0)
remote_endpt = vstring_alloc(20);
vstring_sprintf(remote_endpt, "[%s]:%s", smtp_state->smtp_client_addr,
smtp_state->smtp_client_port);
attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)),
SEND_ATTR_INT(TLS_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER),
SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
SEND_ATTR_STR(TLS_ATTR_SERVERID, MAIL_SERVICE_SMTPD), /* XXX */
ATTR_TYPE_END);
if (vstream_fflush(tlsproxy_stream) != 0) {
msg_warn("error sending request to %s service: %m", psc_tlsp_service);
PSC_SEND_REPLY(smtp_state,
"454 4.7.0 TLS not available due to local problem\r\n");
PSC_STARTTLS_EVENT_ERR_RESUME_RETURN();
}
/*
* Set up a read event for the next phase of the TLS proxy handshake.
*/
PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_finish,
(void *) starttls_state, TLSPROXY_INIT_TIMEOUT);
}
/* psc_starttls_open - open negotiations with TLS proxy */
@ -193,12 +276,10 @@ void psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event)
PSC_STARTTLS *starttls_state;
VSTREAM *tlsproxy_stream;
int fd;
static VSTRING *remote_endpt = 0;
if (psc_tlsp_service == 0) {
psc_tlsp_service = concatenate(MAIL_CLASS_PRIVATE "/",
var_tlsproxy_service, (char *) 0);
remote_endpt = vstring_alloc(20);
}
/*
@ -213,38 +294,16 @@ void psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event)
return;
}
if (msg_verbose)
msg_info("%s: send client name/address on proxy socket %d"
msg_info("%s: connecting to proxy socket %d"
" for smtp socket %d from [%s]:%s flags=%s",
myname, fd, vstream_fileno(smtp_state->smtp_client_stream),
smtp_state->smtp_client_addr, smtp_state->smtp_client_port,
psc_print_state_flags(smtp_state->flags, myname));
/*
* Initial handshake. Send the data attributes now, and send the client
* file descriptor in a later transaction. We report all errors
* asynchronously, to avoid having to maintain multiple delivery paths.
*
* XXX The formatted endpoint should be a state member. Then, we can
* simplify all the format strings throughout the program.
*/
tlsproxy_stream = vstream_fdopen(fd, O_RDWR);
vstring_sprintf(remote_endpt, "[%s]:%s", smtp_state->smtp_client_addr,
smtp_state->smtp_client_port);
attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)),
SEND_ATTR_INT(TLS_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER),
SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
SEND_ATTR_INT(TLS_ATTR_TIMEOUT, psc_normal_cmd_time_limit),
SEND_ATTR_STR(TLS_ATTR_SERVERID, MAIL_SERVICE_SMTPD), /* XXX */
ATTR_TYPE_END);
if (vstream_fflush(tlsproxy_stream) != 0) {
msg_warn("error sending request to %s service: %m", psc_tlsp_service);
vstream_fclose(tlsproxy_stream);
PSC_SEND_REPLY(smtp_state,
"454 4.7.0 TLS not available due to local problem\r\n");
event_request_timer(resume_event, (void *) smtp_state, 0);
return;
}
vstream_control(tlsproxy_stream,
VSTREAM_CTL_PATH, psc_tlsp_service,
VSTREAM_CTL_END);
/*
* Set up a read event for the next phase of the TLS proxy handshake.
@ -253,6 +312,6 @@ void psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event)
starttls_state->tlsproxy_stream = tlsproxy_stream;
starttls_state->resume_event = resume_event;
starttls_state->smtp_state = smtp_state;
PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_finish,
PSC_READ_EVENT_REQUEST(vstream_fileno(tlsproxy_stream), psc_starttls_first,
(void *) starttls_state, TLSPROXY_INIT_TIMEOUT);
}

View File

@ -745,6 +745,21 @@ static void pre_accept(char *unused_name, char **unused_argv)
}
}
/* post_accept - anounce our protocol name */
static void post_accept(VSTREAM *stream, char *unused_name, char **unused_argv,
HTABLE *unused_attr)
{
/*
* Announce the protocol.
*/
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_PROXYMAP),
ATTR_TYPE_END);
(void) vstream_fflush(stream);
}
MAIL_VERSION_STAMP_DECLARE;
/* main - pass control to the multi-threaded skeleton */
@ -782,6 +797,7 @@ int main(int argc, char **argv)
CA_MAIL_SERVER_STR_TABLE(str_table),
CA_MAIL_SERVER_POST_INIT(post_jail_init),
CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
CA_MAIL_SERVER_POST_ACCEPT(post_accept),
/* XXX CA_MAIL_SERVER_SOLITARY if proxywrite */
0);
}

View File

@ -108,18 +108,16 @@ int qmgr_deliver_concurrency;
static int qmgr_deliver_initial_reply(VSTREAM *stream)
{
int stat;
if (peekfd(vstream_fileno(stream)) < 0) {
msg_warn("%s: premature disconnect", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH);
} else if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_INT(MAIL_ATTR_STATUS, &stat),
ATTR_TYPE_END) != 1) {
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_DELIVER),
ATTR_TYPE_END) != 0) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
return (DELIVER_STAT_CRASH);
return (DELIVER_STAT_DEFER);
} else {
return (stat ? DELIVER_STAT_DEFER : 0);
return (0);
}
}

View File

@ -544,6 +544,21 @@ static void post_jail_init(char *unused_name, char **unused_argv)
scache_start_time = event_time();
}
/* scache_post_accept - announce our protocol */
static void scache_post_accept(VSTREAM *stream, char *unused_name,
char **unused_argv, HTABLE *unused_table)
{
/*
* Announce the protocol.
*/
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SCACHE),
ATTR_TYPE_END);
(void) vstream_fflush(stream);
}
MAIL_VERSION_STAMP_DECLARE;
/* main - pass control to the multi-threaded skeleton */
@ -564,6 +579,7 @@ int main(int argc, char **argv)
multi_server_main(argc, argv, scache_service,
CA_MAIL_SERVER_TIME_TABLE(time_table),
CA_MAIL_SERVER_POST_INIT(post_jail_init),
CA_MAIL_SERVER_POST_ACCEPT(scache_post_accept),
CA_MAIL_SERVER_EXIT(scache_status_dump),
CA_MAIL_SERVER_SOLITARY,
0);

View File

@ -360,6 +360,13 @@ static void showq_service(VSTREAM *client, char *unused_service, char **argv)
if (argv[0])
msg_fatal("unexpected command-line argument: %s", argv[0]);
/*
* Protocol identification.
*/
(void) attr_print(client, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SHOWQ),
ATTR_TYPE_END);
/*
* Skip any files that have the wrong permissions. If we can't open an
* existing file, assume the system is out of resources or that it is

View File

@ -280,7 +280,6 @@ smtpd_chat.o: ../../include/mail_params.h
smtpd_chat.o: ../../include/mail_proto.h
smtpd_chat.o: ../../include/mail_stream.h
smtpd_chat.o: ../../include/maps.h
smtpd_chat.o: ../../include/match_list.h
smtpd_chat.o: ../../include/milter.h
smtpd_chat.o: ../../include/msg.h
smtpd_chat.o: ../../include/myaddrinfo.h
@ -296,7 +295,6 @@ smtpd_chat.o: ../../include/smtp_reply_footer.h
smtpd_chat.o: ../../include/smtp_stream.h
smtpd_chat.o: ../../include/smtputf8.h
smtpd_chat.o: ../../include/sock_addr.h
smtpd_chat.o: ../../include/string_list.h
smtpd_chat.o: ../../include/stringops.h
smtpd_chat.o: ../../include/sys_defs.h
smtpd_chat.o: ../../include/tls.h
@ -400,7 +398,6 @@ smtpd_expand.o: ../../include/mac_parse.h
smtpd_expand.o: ../../include/mail_params.h
smtpd_expand.o: ../../include/mail_proto.h
smtpd_expand.o: ../../include/mail_stream.h
smtpd_expand.o: ../../include/match_list.h
smtpd_expand.o: ../../include/milter.h
smtpd_expand.o: ../../include/msg.h
smtpd_expand.o: ../../include/myaddrinfo.h
@ -409,7 +406,6 @@ smtpd_expand.o: ../../include/name_code.h
smtpd_expand.o: ../../include/name_mask.h
smtpd_expand.o: ../../include/nvtable.h
smtpd_expand.o: ../../include/sock_addr.h
smtpd_expand.o: ../../include/string_list.h
smtpd_expand.o: ../../include/stringops.h
smtpd_expand.o: ../../include/sys_defs.h
smtpd_expand.o: ../../include/tls.h
@ -428,7 +424,6 @@ smtpd_haproxy.o: ../../include/htable.h
smtpd_haproxy.o: ../../include/iostuff.h
smtpd_haproxy.o: ../../include/mail_params.h
smtpd_haproxy.o: ../../include/mail_stream.h
smtpd_haproxy.o: ../../include/match_list.h
smtpd_haproxy.o: ../../include/milter.h
smtpd_haproxy.o: ../../include/msg.h
smtpd_haproxy.o: ../../include/myaddrinfo.h
@ -438,7 +433,6 @@ smtpd_haproxy.o: ../../include/name_mask.h
smtpd_haproxy.o: ../../include/nvtable.h
smtpd_haproxy.o: ../../include/smtp_stream.h
smtpd_haproxy.o: ../../include/sock_addr.h
smtpd_haproxy.o: ../../include/string_list.h
smtpd_haproxy.o: ../../include/stringops.h
smtpd_haproxy.o: ../../include/sys_defs.h
smtpd_haproxy.o: ../../include/tls.h
@ -456,7 +450,6 @@ smtpd_milter.o: ../../include/dns.h
smtpd_milter.o: ../../include/htable.h
smtpd_milter.o: ../../include/mail_params.h
smtpd_milter.o: ../../include/mail_stream.h
smtpd_milter.o: ../../include/match_list.h
smtpd_milter.o: ../../include/milter.h
smtpd_milter.o: ../../include/myaddrinfo.h
smtpd_milter.o: ../../include/mymalloc.h
@ -468,7 +461,6 @@ smtpd_milter.o: ../../include/quote_flags.h
smtpd_milter.o: ../../include/resolve_clnt.h
smtpd_milter.o: ../../include/sock_addr.h
smtpd_milter.o: ../../include/split_at.h
smtpd_milter.o: ../../include/string_list.h
smtpd_milter.o: ../../include/stringops.h
smtpd_milter.o: ../../include/sys_defs.h
smtpd_milter.o: ../../include/tls.h
@ -491,7 +483,6 @@ smtpd_peer.o: ../../include/iostuff.h
smtpd_peer.o: ../../include/mail_params.h
smtpd_peer.o: ../../include/mail_proto.h
smtpd_peer.o: ../../include/mail_stream.h
smtpd_peer.o: ../../include/match_list.h
smtpd_peer.o: ../../include/milter.h
smtpd_peer.o: ../../include/msg.h
smtpd_peer.o: ../../include/myaddrinfo.h
@ -501,7 +492,6 @@ smtpd_peer.o: ../../include/name_mask.h
smtpd_peer.o: ../../include/nvtable.h
smtpd_peer.o: ../../include/sock_addr.h
smtpd_peer.o: ../../include/split_at.h
smtpd_peer.o: ../../include/string_list.h
smtpd_peer.o: ../../include/stringops.h
smtpd_peer.o: ../../include/sys_defs.h
smtpd_peer.o: ../../include/tls.h
@ -525,7 +515,6 @@ smtpd_proxy.o: ../../include/mail_params.h
smtpd_proxy.o: ../../include/mail_proto.h
smtpd_proxy.o: ../../include/mail_queue.h
smtpd_proxy.o: ../../include/mail_stream.h
smtpd_proxy.o: ../../include/match_list.h
smtpd_proxy.o: ../../include/milter.h
smtpd_proxy.o: ../../include/msg.h
smtpd_proxy.o: ../../include/myaddrinfo.h
@ -537,7 +526,6 @@ smtpd_proxy.o: ../../include/rec_type.h
smtpd_proxy.o: ../../include/record.h
smtpd_proxy.o: ../../include/smtp_stream.h
smtpd_proxy.o: ../../include/sock_addr.h
smtpd_proxy.o: ../../include/string_list.h
smtpd_proxy.o: ../../include/stringops.h
smtpd_proxy.o: ../../include/sys_defs.h
smtpd_proxy.o: ../../include/tls.h
@ -607,7 +595,6 @@ smtpd_sasl_proto.o: ../../include/mail_error.h
smtpd_sasl_proto.o: ../../include/mail_params.h
smtpd_sasl_proto.o: ../../include/mail_proto.h
smtpd_sasl_proto.o: ../../include/mail_stream.h
smtpd_sasl_proto.o: ../../include/match_list.h
smtpd_sasl_proto.o: ../../include/milter.h
smtpd_sasl_proto.o: ../../include/msg.h
smtpd_sasl_proto.o: ../../include/myaddrinfo.h
@ -616,7 +603,6 @@ smtpd_sasl_proto.o: ../../include/name_code.h
smtpd_sasl_proto.o: ../../include/name_mask.h
smtpd_sasl_proto.o: ../../include/nvtable.h
smtpd_sasl_proto.o: ../../include/sock_addr.h
smtpd_sasl_proto.o: ../../include/string_list.h
smtpd_sasl_proto.o: ../../include/stringops.h
smtpd_sasl_proto.o: ../../include/sys_defs.h
smtpd_sasl_proto.o: ../../include/tls.h
@ -641,7 +627,6 @@ smtpd_state.o: ../../include/mail_error.h
smtpd_state.o: ../../include/mail_params.h
smtpd_state.o: ../../include/mail_proto.h
smtpd_state.o: ../../include/mail_stream.h
smtpd_state.o: ../../include/match_list.h
smtpd_state.o: ../../include/milter.h
smtpd_state.o: ../../include/msg.h
smtpd_state.o: ../../include/myaddrinfo.h
@ -650,7 +635,6 @@ smtpd_state.o: ../../include/name_code.h
smtpd_state.o: ../../include/name_mask.h
smtpd_state.o: ../../include/nvtable.h
smtpd_state.o: ../../include/sock_addr.h
smtpd_state.o: ../../include/string_list.h
smtpd_state.o: ../../include/sys_defs.h
smtpd_state.o: ../../include/tls.h
smtpd_state.o: ../../include/vbuf.h
@ -676,7 +660,6 @@ smtpd_xforward.o: ../../include/htable.h
smtpd_xforward.o: ../../include/iostuff.h
smtpd_xforward.o: ../../include/mail_proto.h
smtpd_xforward.o: ../../include/mail_stream.h
smtpd_xforward.o: ../../include/match_list.h
smtpd_xforward.o: ../../include/milter.h
smtpd_xforward.o: ../../include/msg.h
smtpd_xforward.o: ../../include/myaddrinfo.h
@ -685,7 +668,6 @@ smtpd_xforward.o: ../../include/name_code.h
smtpd_xforward.o: ../../include/name_mask.h
smtpd_xforward.o: ../../include/nvtable.h
smtpd_xforward.o: ../../include/sock_addr.h
smtpd_xforward.o: ../../include/string_list.h
smtpd_xforward.o: ../../include/sys_defs.h
smtpd_xforward.o: ../../include/tls.h
smtpd_xforward.o: ../../include/vbuf.h

View File

@ -62,6 +62,7 @@ depend: $(MAKES)
spawn.o: ../../include/argv.h
spawn.o: ../../include/check_arg.h
spawn.o: ../../include/dict.h
spawn.o: ../../include/htable.h
spawn.o: ../../include/mail_conf.h
spawn.o: ../../include/mail_params.h
spawn.o: ../../include/mail_parm_split.h

View File

@ -107,6 +107,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -144,6 +149,15 @@
static ATTR_CLNT *tls_mgr;
/* tls_mgr_handshake - receive server protocol announcement */
static int tls_mgr_handshake(VSTREAM *stream)
{
return (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSMGR),
ATTR_TYPE_END));
}
/* tls_mgr_open - create client handle */
static void tls_mgr_open(void)
@ -168,6 +182,7 @@ static void tls_mgr_open(void)
attr_clnt_control(tls_mgr,
ATTR_CLNT_CTL_PROTO, attr_vprint, attr_vscan,
ATTR_CLNT_CTL_HANDSHAKE, tls_mgr_handshake,
ATTR_CLNT_CTL_END);
}

View File

@ -187,6 +187,14 @@ VSTREAM *tls_proxy_open(const char *service, int flags,
* remote peer file descriptor in a later transaction.
*/
tlsproxy_stream = vstream_fdopen(fd, O_RDWR);
if (attr_scan(tlsproxy_stream, ATTR_FLAG_STRICT,
RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSPROXY),
ATTR_TYPE_END) != 0) {
msg_warn("error receiving %s service initial response",
STR(tlsproxy_service));
vstream_fclose(tlsproxy_stream);
return (0);
}
vstring_sprintf(remote_endpt, "[%s]:%s", peer_addr, peer_port);
attr_print(tlsproxy_stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(TLS_ATTR_REMOTE_ENDPT, STR(remote_endpt)),

View File

@ -1004,6 +1004,22 @@ static void tlsmgr_post_init(char *unused_name, char **unused_argv)
tlsmgr_cache_run_event(NULL_EVENT, (void *) ent);
}
/* tlsmgr_post_accept - announce our protocol */
static void tlsmgr_post_accept(VSTREAM *stream, char *unused_name,
char **unused_argv, HTABLE *unused_table)
{
/*
* Announce the protocol.
*/
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSMGR),
ATTR_TYPE_END);
(void) vstream_fflush(stream);
}
/* tlsmgr_before_exit - save PRNG state before exit */
static void tlsmgr_before_exit(char *unused_service_name, char **unused_argv)
@ -1061,6 +1077,7 @@ int main(int argc, char **argv)
CA_MAIL_SERVER_STR_TABLE(str_table),
CA_MAIL_SERVER_PRE_INIT(tlsmgr_pre_init),
CA_MAIL_SERVER_POST_INIT(tlsmgr_post_init),
CA_MAIL_SERVER_POST_ACCEPT(tlsmgr_post_accept),
CA_MAIL_SERVER_EXIT(tlsmgr_before_exit),
CA_MAIL_SERVER_LOOP(tlsmgr_loop),
CA_MAIL_SERVER_SOLITARY,

View File

@ -1481,6 +1481,12 @@ static void tlsp_service(VSTREAM *plaintext_stream,
CA_VSTREAM_CTL_TIMEOUT(5),
CA_VSTREAM_CTL_END);
(void) attr_print(plaintext_stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TLSPROXY),
ATTR_TYPE_END);
if (vstream_fflush(plaintext_stream) != 0)
msg_warn("write %s attribute: %m", MAIL_ATTR_PROTO);
/*
* Receive postscreen's remote SMTP client address/port and socket.
*/

View File

@ -153,7 +153,7 @@
/* matches subdomains of example.com,
/* instead of requiring an explicit ".example.com" pattern.
/* .IP "\fBrelayhost (empty)\fR"
/* The next-hop destination of non-local mail; overrides non-local
/* The next-hop destination(s) for non-local mail; overrides non-local
/* domains in recipient addresses.
/* .IP "\fBtransport_maps (empty)\fR"
/* Optional lookup tables with mappings from recipient address to
@ -522,6 +522,21 @@ static void pre_accept(char *unused_name, char **unused_argv)
#endif
/* post_accept - anounce our protocol name */
static void post_accept(VSTREAM *stream, char *unused_name, char **unused_argv,
HTABLE *unused_attr)
{
/*
* Announce the protocol.
*/
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_TRIVIAL),
ATTR_TYPE_END);
(void) vstream_fflush(stream);
}
static void check_table_stats(int unused_event, void *unused_context)
{
const char *table;
@ -648,5 +663,6 @@ int main(int argc, char **argv)
#ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
#endif
CA_MAIL_SERVER_POST_ACCEPT(post_accept),
0);
}

View File

@ -17,7 +17,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
msg_output.c msg_syslog.c msg_vstream.c mvect.c myaddrinfo.c myflock.c \
mymalloc.c myrand.c mystrtok.c name_code.c name_mask.c netstring.c \
neuter.c non_blocking.c nvtable.c open_as.c open_limit.c open_lock.c \
peekfd.c percentm.c posix_signals.c printable.c rand_sleep.c \
peekfd.c posix_signals.c printable.c rand_sleep.c \
readlline.c ring.c safe_getenv.c safe_open.c \
sane_accept.c sane_connect.c sane_link.c sane_rename.c \
sane_socketpair.c sane_time.c scan_dir.c set_eugid.c set_ugid.c \
@ -62,7 +62,7 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
msg_output.o msg_syslog.o msg_vstream.o mvect.o myaddrinfo.o myflock.o \
mymalloc.o myrand.o mystrtok.o name_code.o name_mask.o netstring.o \
neuter.o non_blocking.o nvtable.o open_as.o open_limit.o open_lock.o \
peekfd.o percentm.o posix_signals.o printable.o rand_sleep.o \
peekfd.o posix_signals.o printable.o rand_sleep.o \
readlline.o ring.o safe_getenv.o safe_open.o \
sane_accept.o sane_connect.o sane_link.o sane_rename.o \
sane_socketpair.o sane_time.o scan_dir.o set_eugid.o set_ugid.o \
@ -104,7 +104,7 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
mac_parse.h make_dirs.h mask_addr.h match_list.h msg.h \
msg_output.h msg_syslog.h msg_vstream.h mvect.h myaddrinfo.h myflock.h \
mymalloc.h myrand.h name_code.h name_mask.h netstring.h nvtable.h \
open_as.h open_lock.h percentm.h posix_signals.h readlline.h ring.h \
open_as.h open_lock.h posix_signals.h readlline.h ring.h \
safe.h safe_open.h sane_accept.h sane_connect.h sane_fsops.h \
load_lib.h \
sane_socketpair.h sane_time.h scan_dir.h set_eugid.h set_ugid.h \
@ -1949,6 +1949,8 @@ load_file.o: vbuf.h
load_file.o: vstream.h
load_file.o: warn_stat.h
load_lib.o: load_lib.c
load_lib.o: load_lib.h
load_lib.o: msg.h
load_lib.o: sys_defs.h
logwriter.o: check_arg.h
logwriter.o: iostuff.h
@ -2070,7 +2072,6 @@ msg_output.o: msg_output.c
msg_output.o: msg_output.h
msg_output.o: msg_vstream.h
msg_output.o: mymalloc.h
msg_output.o: percentm.h
msg_output.o: stringops.h
msg_output.o: sys_defs.h
msg_output.o: vbuf.h
@ -2220,12 +2221,6 @@ pass_trigger.o: trigger.h
peekfd.o: iostuff.h
peekfd.o: peekfd.c
peekfd.o: sys_defs.h
percentm.o: check_arg.h
percentm.o: percentm.c
percentm.o: percentm.h
percentm.o: sys_defs.h
percentm.o: vbuf.h
percentm.o: vstring.h
poll_fd.o: iostuff.h
poll_fd.o: msg.h
poll_fd.o: poll_fd.c

View File

@ -45,6 +45,7 @@ typedef int (*ATTR_PRINT_CUSTOM_FN) (ATTR_PRINT_COMMON_FN, VSTREAM *, int, void
#define ATTR_TYPE_LONG 4 /* Unsigned long */
#define ATTR_TYPE_DATA 5 /* Binary data */
#define ATTR_TYPE_FUNC 6 /* Function pointer */
#define ATTR_TYPE_STREQ 7 /* Requires (name, value) match */
/*
* Optional sender-specified grouping for hash or nameval tables.
@ -70,6 +71,7 @@ typedef int (*ATTR_PRINT_CUSTOM_FN) (ATTR_PRINT_COMMON_FN, VSTREAM *, int, void
#define RECV_ATTR_INT(name, val) ATTR_TYPE_INT, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, int, (val))
#define RECV_ATTR_STR(name, val) ATTR_TYPE_STR, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, VSTRING, (val))
#define RECV_ATTR_STREQ(name, val) ATTR_TYPE_STREQ, CHECK_CPTR(ATTR, char, (name)), CHECK_CPTR(ATTR, char, (val))
#define RECV_ATTR_HASH(val) ATTR_TYPE_HASH, CHECK_PTR(ATTR, HTABLE, (val))
#define RECV_ATTR_NV(val) ATTR_TYPE_NV, CHECK_PTR(ATTR, NVTABLE, (val))
#define RECV_ATTR_LONG(name, val) ATTR_TYPE_LONG, CHECK_CPTR(ATTR, char, (name)), CHECK_PTR(ATTR, long, (val))

View File

@ -8,6 +8,7 @@
/*
/* typedef int (*ATTR_CLNT_PRINT_FN) (VSTREAM *, int, va_list);
/* typedef int (*ATTR_CLNT_SCAN_FN) (VSTREAM *, int, va_list);
/* typedef int (*ATTR_CLNT_HANDSHAKE_FN) (VSTREAM *);
/*
/* ATTR_CLNT *attr_clnt_create(server, timeout, max_idle, max_ttl)
/* const char *server;
@ -65,6 +66,9 @@
/* .IP "ATTR_CLNT_CTL_TRY_DELAY(int)"
/* The time in seconds between attempts to send a request
/* (default: 1). Specify a value greater than zero.
/* .IP "ATTR_CLNT_CTL_HANDSHAKE(VSTREAM *)"
/* A pointer to function that will be called at the start of a
/* new connection, and that returns 0 in case of success.
/* DIAGNOSTICS
/* Warnings: communication failure.
/* SEE ALSO
@ -80,6 +84,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -254,6 +263,12 @@ void attr_clnt_control(ATTR_CLNT *client, int name,...)
client->print = va_arg(ap, ATTR_CLNT_PRINT_FN);
client->scan = va_arg(ap, ATTR_CLNT_SCAN_FN);
break;
case ATTR_CLNT_CTL_HANDSHAKE:
auto_clnt_control(client->auto_clnt,
AUTO_CLNT_CTL_HANDSHAKE,
va_arg(ap, ATTR_CLNT_HANDSHAKE_FN),
AUTO_CLNT_CTL_END);
break;
case ATTR_CLNT_CTL_REQ_LIMIT:
client->req_limit = va_arg(ap, int);
if (client->req_limit < 0)

View File

@ -27,6 +27,7 @@
typedef struct ATTR_CLNT ATTR_CLNT;
typedef int (*ATTR_CLNT_PRINT_FN) (VSTREAM *, int, va_list);
typedef int (*ATTR_CLNT_SCAN_FN) (VSTREAM *, int, va_list);
typedef int (*ATTR_CLNT_HANDSHAKE_FN) (VSTREAM *);
extern ATTR_CLNT *attr_clnt_create(const char *, int, int, int);
extern int attr_clnt_request(ATTR_CLNT *, int,...);
@ -38,6 +39,7 @@ extern void attr_clnt_control(ATTR_CLNT *, int,...);
#define ATTR_CLNT_CTL_REQ_LIMIT 2 /* requests per connection */
#define ATTR_CLNT_CTL_TRY_LIMIT 3 /* attempts per request */
#define ATTR_CLNT_CTL_TRY_DELAY 4 /* pause between requests */
#define ATTR_CLNT_CTL_HANDSHAKE 5 /* handshake before first request */
/* LICENSE
/* .ad
@ -48,6 +50,11 @@ extern void attr_clnt_control(ATTR_CLNT *, int,...);
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
#endif

View File

@ -228,6 +228,7 @@ int main(int unused_argc, char **argv)
htable_enter(table, "foo-name", mystrdup("foo-value"));
htable_enter(table, "bar-name", mystrdup("bar-value"));
attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
@ -236,11 +237,15 @@ int main(int unused_argc, char **argv)
SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
ATTR_TYPE_END);
attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
ATTR_TYPE_END);
attr_print0(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "not-test"),
ATTR_TYPE_END);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");

View File

@ -269,6 +269,7 @@ int main(int unused_argc, char **argv)
htable_enter(table, "foo-name", mystrdup("foo-value"));
htable_enter(table, "bar-name", mystrdup("bar-value"));
attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
@ -277,11 +278,15 @@ int main(int unused_argc, char **argv)
SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
ATTR_TYPE_END);
attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
ATTR_TYPE_END);
attr_print64(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "not-test"),
ATTR_TYPE_END);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");

View File

@ -224,6 +224,7 @@ int main(int unused_argc, char **argv)
htable_enter(table, "foo-name", mystrdup("foo-value"));
htable_enter(table, "bar-name", mystrdup("bar-value"));
attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
@ -232,11 +233,15 @@ int main(int unused_argc, char **argv)
SEND_ATTR_LONG(ATTR_NAME_LONG, 4321L),
ATTR_TYPE_END);
attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "test"),
SEND_ATTR_INT(ATTR_NAME_INT, 4711),
SEND_ATTR_LONG(ATTR_NAME_LONG, 1234L),
SEND_ATTR_STR(ATTR_NAME_STR, "whoopee"),
SEND_ATTR_DATA(ATTR_NAME_DATA, strlen("whoopee"), "whoopee"),
ATTR_TYPE_END);
attr_print_plain(VSTREAM_OUT, ATTR_FLAG_NONE,
SEND_ATTR_STR("protocol", "not-test"),
ATTR_TYPE_END);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");

View File

@ -100,6 +100,9 @@
/* This argument is followed by an attribute name and a long pointer.
/* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_STREQ(const char *name, const char *value)"
/* The name and value must match what the client sends.
/* This attribute does not increment the result value.
/* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)"
@ -278,6 +281,7 @@ int attr_vscan0(VSTREAM *fp, int flags, va_list ap)
int conversions;
ATTR_SCAN_CUSTOM_FN scan_fn;
void *scan_arg;
const char *expect_val;
/*
* Sanity check.
@ -421,6 +425,19 @@ int attr_vscan0(VSTREAM *fp, int flags, va_list ap)
if (scan_fn(attr_scan0, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
return (-1);
break;
case ATTR_TYPE_STREQ:
expect_val = va_arg(ap, const char *);
if ((ch = attr_scan0_string(fp, str_buf,
"input attribute value")) < 0)
return (-1);
if (strcmp(expect_val, STR(str_buf)) != 0) {
msg_warn("unexpected %s %s from %s (expected: %s)",
STR(name_buf), STR(str_buf), VSTREAM_PATH(fp),
expect_val);
return (-1);
}
conversions -= 1;
break;
case ATTR_TYPE_HASH:
case ATTR_TYPE_CLOSE:
if ((ch = attr_scan0_string(fp, str_buf,
@ -513,6 +530,7 @@ int main(int unused_argc, char **used_argv)
msg_vstream_init(used_argv[0], VSTREAM_ERR);
if ((ret = attr_scan0(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -534,6 +552,7 @@ int main(int unused_argc, char **used_argv)
}
if ((ret = attr_scan0(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -550,6 +569,11 @@ int main(int unused_argc, char **used_argv)
} else {
vstream_printf("return: %d\n", ret);
}
if ((ret = attr_scan0(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
ATTR_TYPE_END)) != 0)
vstream_printf("return: %d\n", ret);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");

View File

@ -1,3 +1,4 @@
./attr_print0: send attr protocol = test
./attr_print0: send attr number = 4711
./attr_print0: send attr long_number = 1234
./attr_print0: send attr string = whoopee
@ -5,10 +6,15 @@
./attr_print0: send attr name foo-name value foo-value
./attr_print0: send attr name bar-name value bar-value
./attr_print0: send attr long_number = 4321
./attr_print0: send attr protocol = test
./attr_print0: send attr number = 4711
./attr_print0: send attr long_number = 1234
./attr_print0: send attr string = whoopee
./attr_print0: send attr data = [data 7 bytes]
./attr_print0: send attr protocol = not-test
./attr_scan0: unknown_stream: wanted attribute: protocol
./attr_scan0: input attribute name: protocol
./attr_scan0: input attribute value: test
./attr_scan0: unknown_stream: wanted attribute: number
./attr_scan0: input attribute name: number
./attr_scan0: input attribute value: 4711
@ -36,6 +42,9 @@
./attr_scan0: input attribute value: 4321
./attr_scan0: unknown_stream: wanted attribute: (list terminator)
./attr_scan0: input attribute name: (end)
./attr_scan0: unknown_stream: wanted attribute: protocol
./attr_scan0: input attribute name: protocol
./attr_scan0: input attribute value: test
./attr_scan0: unknown_stream: wanted attribute: number
./attr_scan0: input attribute name: number
./attr_scan0: input attribute value: 4711
@ -50,6 +59,10 @@
./attr_scan0: input attribute value: d2hvb3BlZQ==
./attr_scan0: unknown_stream: wanted attribute: (list terminator)
./attr_scan0: input attribute name: (end)
./attr_scan0: unknown_stream: wanted attribute: protocol
./attr_scan0: input attribute name: protocol
./attr_scan0: input attribute value: not-test
./attr_scan0: warning: unexpected protocol not-test from unknown_stream (expected: test)
number 4711
long_number 1234
string whoopee
@ -63,3 +76,4 @@ string whoopee
data whoopee
(hash) foo-name foo-value
(hash) bar-name bar-value
return: -1

View File

@ -102,6 +102,9 @@
/* This argument is followed by an attribute name and a long pointer.
/* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_STREQ(const char *name, const char *value)"
/* The name and value must match what the client sends.
/* This attribute does not increment the result value.
/* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)"
@ -281,6 +284,7 @@ int attr_vscan64(VSTREAM *fp, int flags, va_list ap)
int conversions;
ATTR_SCAN_CUSTOM_FN scan_fn;
void *scan_arg;
const char *expect_val;
/*
* Sanity check.
@ -470,6 +474,29 @@ int attr_vscan64(VSTREAM *fp, int flags, va_list ap)
if (scan_fn(attr_scan64, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
return (-1);
break;
case ATTR_TYPE_STREQ:
if (ch != ':') {
msg_warn("missing value for string attribute %s from %s",
STR(name_buf), VSTREAM_PATH(fp));
return (-1);
}
expect_val = va_arg(ap, const char *);
if ((ch = attr_scan64_string(fp, str_buf,
"input attribute value")) < 0)
return (-1);
if (ch != '\n') {
msg_warn("multiple values for attribute %s from %s",
STR(name_buf), VSTREAM_PATH(fp));
return (-1);
}
if (strcmp(expect_val, STR(str_buf)) != 0) {
msg_warn("unexpected %s %s from %s (expected: %s)",
STR(name_buf), STR(str_buf), VSTREAM_PATH(fp),
expect_val);
return (-1);
}
conversions -= 1;
break;
case ATTR_TYPE_HASH:
case ATTR_TYPE_CLOSE:
if (ch != ':') {
@ -572,6 +599,7 @@ int main(int unused_argc, char **used_argv)
msg_vstream_init(used_argv[0], VSTREAM_ERR);
if ((ret = attr_scan64(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -593,6 +621,7 @@ int main(int unused_argc, char **used_argv)
}
if ((ret = attr_scan64(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -609,6 +638,11 @@ int main(int unused_argc, char **used_argv)
} else {
vstream_printf("return: %d\n", ret);
}
if ((ret = attr_scan64(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
ATTR_TYPE_END)) != 0)
vstream_printf("return: %d\n", ret);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");

View File

@ -1,3 +1,4 @@
./attr_print64: send attr protocol = test
./attr_print64: send attr number = 4711
./attr_print64: send attr long_number = 1234
./attr_print64: send attr string = whoopee
@ -5,10 +6,15 @@
./attr_print64: send attr name foo-name value foo-value
./attr_print64: send attr name bar-name value bar-value
./attr_print64: send attr long_number = 4321
./attr_print64: send attr protocol = test
./attr_print64: send attr number = 4711
./attr_print64: send attr long_number = 1234
./attr_print64: send attr string = whoopee
./attr_print64: send attr data = [data 7 bytes]
./attr_print64: send attr protocol = not-test
./attr_scan64: unknown_stream: wanted attribute: protocol
./attr_scan64: input attribute name: protocol
./attr_scan64: input attribute value: test
./attr_scan64: unknown_stream: wanted attribute: number
./attr_scan64: input attribute name: number
./attr_scan64: input attribute value: 4711
@ -36,6 +42,9 @@
./attr_scan64: input attribute value: 4321
./attr_scan64: unknown_stream: wanted attribute: (list terminator)
./attr_scan64: input attribute name: (end)
./attr_scan64: unknown_stream: wanted attribute: protocol
./attr_scan64: input attribute name: protocol
./attr_scan64: input attribute value: test
./attr_scan64: unknown_stream: wanted attribute: number
./attr_scan64: input attribute name: number
./attr_scan64: input attribute value: 4711
@ -50,6 +59,10 @@
./attr_scan64: input attribute value: whoopee
./attr_scan64: unknown_stream: wanted attribute: (list terminator)
./attr_scan64: input attribute name: (end)
./attr_scan64: unknown_stream: wanted attribute: protocol
./attr_scan64: input attribute name: protocol
./attr_scan64: input attribute value: not-test
./attr_scan64: warning: unexpected protocol not-test from unknown_stream (expected: test)
number 4711
long_number 1234
string whoopee
@ -63,3 +76,4 @@ string whoopee
data whoopee
(hash) foo-name foo-value
(hash) bar-name bar-value
return: -1

View File

@ -100,6 +100,9 @@
/* This argument is followed by an attribute name and a long pointer.
/* .IP "RECV_ATTR_STR(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_STREQ(const char *name, const char *value)"
/* The name and value must match what the client sends.
/* This attribute does not increment the result value.
/* .IP "RECV_ATTR_DATA(const char *name, VSTRING *vp)"
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "RECV_ATTR_FUNC(ATTR_SCAN_CUSTOM_FN, void *data)"
@ -294,6 +297,7 @@ int attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
int conversions;
ATTR_SCAN_CUSTOM_FN scan_fn;
void *scan_arg;
const char *expect_val;
/*
* Sanity check.
@ -458,6 +462,24 @@ int attr_vscan_plain(VSTREAM *fp, int flags, va_list ap)
if (scan_fn(attr_scan_plain, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
return (-1);
break;
case ATTR_TYPE_STREQ:
if (ch != '=') {
msg_warn("missing value for string attribute %s from %s",
STR(name_buf), VSTREAM_PATH(fp));
return (-1);
}
expect_val = va_arg(ap, const char *);
if ((ch = attr_scan_plain_string(fp, str_buf, 0,
"input attribute value")) < 0)
return (-1);
if (strcmp(expect_val, STR(str_buf)) != 0) {
msg_warn("unexpected %s %s from %s (expected: %s)",
STR(name_buf), STR(str_buf), VSTREAM_PATH(fp),
expect_val);
return (-1);
}
conversions -= 1;
break;
case ATTR_TYPE_HASH:
case ATTR_TYPE_CLOSE:
if (ch != '=') {
@ -555,6 +577,7 @@ int main(int unused_argc, char **used_argv)
msg_vstream_init(used_argv[0], VSTREAM_ERR);
if ((ret = attr_scan_plain(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -576,6 +599,7 @@ int main(int unused_argc, char **used_argv)
}
if ((ret = attr_scan_plain(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
RECV_ATTR_INT(ATTR_NAME_INT, &int_val),
RECV_ATTR_LONG(ATTR_NAME_LONG, &long_val),
RECV_ATTR_STR(ATTR_NAME_STR, str_val),
@ -592,6 +616,11 @@ int main(int unused_argc, char **used_argv)
} else {
vstream_printf("return: %d\n", ret);
}
if ((ret = attr_scan_plain(VSTREAM_IN,
ATTR_FLAG_STRICT,
RECV_ATTR_STREQ("protocol", "test"),
ATTR_TYPE_END)) != 0)
vstream_printf("return: %d\n", ret);
if (vstream_fflush(VSTREAM_OUT) != 0)
msg_fatal("write error: %m");

View File

@ -1,3 +1,4 @@
./attr_print_plain: send attr protocol = test
./attr_print_plain: send attr number = 4711
./attr_print_plain: send attr long_number = 1234
./attr_print_plain: send attr string = whoopee
@ -5,10 +6,15 @@
./attr_print_plain: send attr name foo-name value foo-value
./attr_print_plain: send attr name bar-name value bar-value
./attr_print_plain: send attr long_number = 4321
./attr_print_plain: send attr protocol = test
./attr_print_plain: send attr number = 4711
./attr_print_plain: send attr long_number = 1234
./attr_print_plain: send attr string = whoopee
./attr_print_plain: send attr data = [data 7 bytes]
./attr_print_plain: send attr protocol = not-test
./attr_scan_plain: unknown_stream: wanted attribute: protocol
./attr_scan_plain: input attribute name: protocol
./attr_scan_plain: input attribute value: test
./attr_scan_plain: unknown_stream: wanted attribute: number
./attr_scan_plain: input attribute name: number
./attr_scan_plain: input attribute value: 4711
@ -36,6 +42,9 @@
./attr_scan_plain: input attribute value: 4321
./attr_scan_plain: unknown_stream: wanted attribute: (list terminator)
./attr_scan_plain: input attribute name: (end)
./attr_scan_plain: unknown_stream: wanted attribute: protocol
./attr_scan_plain: input attribute name: protocol
./attr_scan_plain: input attribute value: test
./attr_scan_plain: unknown_stream: wanted attribute: number
./attr_scan_plain: input attribute name: number
./attr_scan_plain: input attribute value: 4711
@ -50,6 +59,10 @@
./attr_scan_plain: input attribute value: d2hvb3BlZQ==
./attr_scan_plain: unknown_stream: wanted attribute: (list terminator)
./attr_scan_plain: input attribute name: (end)
./attr_scan_plain: unknown_stream: wanted attribute: protocol
./attr_scan_plain: input attribute name: protocol
./attr_scan_plain: input attribute value: not-test
./attr_scan_plain: warning: unexpected protocol not-test from unknown_stream (expected: test)
number 4711
long_number 1234
string whoopee
@ -63,3 +76,4 @@ string whoopee
data whoopee
(hash) foo-name foo-value
(hash) bar-name bar-value
return: -1

View File

@ -6,6 +6,8 @@
/* SYNOPSIS
/* #include <auto_clnt.h>
/*
/* typedef void (*AUTO_CLNT_HANDSHAKE_FN)(VSTREAM *);
/*
/* AUTO_CLNT *auto_clnt_create(service, timeout, max_idle, max_ttl)
/* const char *service;
/* int timeout;
@ -23,6 +25,10 @@
/*
/* void auto_clnt_free(auto_clnt)
/* AUTO_CLNT *auto_clnt;
/*
/* void auto_clnt_control(auto_clnt, name, value, ... AUTO_CLNT_CTL_END)
/* AUTO_CLNT *auto_clnt;
/* int name;
/* DESCRIPTION
/* This module maintains IPC client endpoints that automatically
/* disconnect after a being idle for a configurable amount of time,
@ -47,6 +53,15 @@
/*
/* auto_clnt_free() destroys of the specified client endpoint.
/*
/* auto_clnt_control() allows the user to fine tune the behavior of
/* the specified client. The arguments are a list of (name, value)
/* terminated with AUTO_CLNT_CTL_END.
/* The following lists the names and the types of the corresponding
/* value arguments.
/* .IP "AUTO_CLNT_CTL_HANDSHAKE(VSTREAM *)"
/* A pointer to function that will be called at the start of a
/* new connection, and that returns 0 in case of success.
/* .PP
/* Arguments:
/* .IP service
/* The service argument specifies "transport:servername" where
@ -79,6 +94,10 @@
/* is expected to set the stream pathname to the server endpoint name.
/* .IP context
/* Application context that is passed to the open_action routine.
/* .IP handshake
/* A null pointer, or a pointer to function that will be called
/* at the start of a new connection and that returns 0 in case
/* of success.
/* DIAGNOSTICS
/* Warnings: communication failure. Fatal error: out of memory.
/* LICENSE
@ -90,6 +109,11 @@
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/* System library. */
@ -120,6 +144,7 @@ struct AUTO_CLNT {
int timeout; /* I/O time limit */
int max_idle; /* time before client disconnect */
int max_ttl; /* time before client disconnect */
AUTO_CLNT_HANDSHAKE_FN handshake; /* new connection only */
int (*connect) (const char *, int, int); /* unix, local, inet */
};
@ -250,6 +275,7 @@ void auto_clnt_recover(AUTO_CLNT *auto_clnt)
VSTREAM *auto_clnt_access(AUTO_CLNT *auto_clnt)
{
AUTO_CLNT_HANDSHAKE_FN handshake;
/*
* Open a stream or restart the idle timer.
@ -258,11 +284,15 @@ VSTREAM *auto_clnt_access(AUTO_CLNT *auto_clnt)
*/
if (auto_clnt->vstream == 0) {
auto_clnt_open(auto_clnt);
handshake = (auto_clnt->vstream ? auto_clnt->handshake : 0);
} else {
if (auto_clnt->max_idle > 0)
event_request_timer(auto_clnt_event, (void *) auto_clnt,
auto_clnt->max_idle);
handshake = 0;
}
if (handshake != 0 && handshake(auto_clnt->vstream) != 0)
return (0);
return (auto_clnt->vstream);
}
@ -290,6 +320,7 @@ AUTO_CLNT *auto_clnt_create(const char *service, int timeout,
auto_clnt->timeout = timeout;
auto_clnt->max_idle = max_idle;
auto_clnt->max_ttl = max_ttl;
auto_clnt->handshake = 0;
if (strcmp(transport, "inet") == 0) {
auto_clnt->connect = inet_connect;
} else if (strcmp(transport, "local") == 0) {
@ -320,3 +351,22 @@ void auto_clnt_free(AUTO_CLNT *auto_clnt)
myfree(auto_clnt->endpoint);
myfree((void *) auto_clnt);
}
/* auto_clnt_control - fine control */
void auto_clnt_control(AUTO_CLNT *client, int name,...)
{
const char *myname = "auto_clnt_control";
va_list ap;
for (va_start(ap, name); name != AUTO_CLNT_CTL_END; name = va_arg(ap, int)) {
switch (name) {
case AUTO_CLNT_CTL_HANDSHAKE:
client->handshake = va_arg(ap, AUTO_CLNT_HANDSHAKE_FN);
break;
default:
msg_panic("%s: bad name %d", myname, name);
}
}
va_end(ap);
}

View File

@ -20,12 +20,17 @@
* External interface.
*/
typedef struct AUTO_CLNT AUTO_CLNT;
typedef int (*AUTO_CLNT_HANDSHAKE_FN) (VSTREAM *);
extern AUTO_CLNT *auto_clnt_create(const char *, int, int, int);
extern VSTREAM *auto_clnt_access(AUTO_CLNT *);
extern void auto_clnt_recover(AUTO_CLNT *);
extern const char *auto_clnt_name(AUTO_CLNT *);
extern void auto_clnt_free(AUTO_CLNT *);
extern void auto_clnt_control(AUTO_CLNT *, int,...);
#define AUTO_CLNT_CTL_END 0
#define AUTO_CLNT_CTL_HANDSHAKE 1 /* handshake before first request */
/* LICENSE
/* .ad
@ -36,6 +41,11 @@ extern void auto_clnt_free(AUTO_CLNT *);
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
#endif

View File

@ -95,7 +95,6 @@
#include <vstream.h>
#include <msg_vstream.h>
#include <stringops.h>
#include <percentm.h>
#include <msg_output.h>
/*
@ -165,7 +164,7 @@ void msg_vprintf(int level, const char *format, va_list ap)
msg_vstream_init("unknown", VSTREAM_ERR);
vp = msg_buffers[msg_vprintf_level - 1];
/* OK if terminating signal handler hijacks control before next stmt. */
vstring_vsprintf(vp, percentm(format, errno), ap);
vstring_vsprintf(vp, format, ap);
printable(vstring_str(vp), '?');
for (i = 0; i < msg_output_fn_count; i++)
msg_output_fn[i] (level, vstring_str(vp));

View File

@ -1,84 +0,0 @@
/*++
/* NAME
/* percentm 3
/* SUMMARY
/* expand %m embedded in string to system error text
/* SYNOPSIS
/* #include <percentm.h>
/*
/* char *percentm(const char *src, int err)
/* DESCRIPTION
/* The percentm() routine makes a copy of the null-terminated string
/* given via the \fIsrc\fR argument, with %m sequences replaced by
/* the system error text corresponding to the \fIerr\fR argument.
/* The result is overwritten upon each successive call.
/*
/* Arguments:
/* .IP src
/* A null-terminated input string with zero or more %m sequences.
/* .IP err
/* A legal \fIerrno\fR value. The text corresponding to this error
/* value is used when expanding %m sequences.
/* SEE ALSO
/* syslog(3) system logger library
/* HISTORY
/* .ad
/* .fi
/* A percentm() routine appears in the TCP Wrapper software
/* by Wietse Venema.
/* 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 libraries. */
#include <sys_defs.h>
#include <string.h>
/* Utility library. */
#include "vstring.h"
#include "percentm.h"
/* percentm - replace %m by error message corresponding to value in err */
char *percentm(const char *str, int err)
{
static VSTRING *vp;
const unsigned char *ip = (const unsigned char *) str;
if (vp == 0)
vp = vstring_alloc(100); /* grows on demand */
VSTRING_RESET(vp);
while (*ip) {
switch (*ip) {
default:
VSTRING_ADDCH(vp, *ip++);
break;
case '%':
switch (ip[1]) {
default: /* leave %<any> alone */
VSTRING_ADDCH(vp, *ip++);
/* FALLTHROUGH */
case '\0': /* don't fall off end */
VSTRING_ADDCH(vp, *ip++);
break;
case 'm': /* replace %m */
vstring_strcat(vp, strerror(err));
ip += 2;
break;
}
}
}
VSTRING_TERMINATE(vp);
return (vstring_str(vp));
}

View File

@ -1,35 +0,0 @@
#ifndef _PERCENT_H_INCLUDED_
#define _PERCENT_H_INCLUDED_
/*++
/* NAME
/* percentm 3h
/* SUMMARY
/* expand %m embedded in string to system error text
/* SYNOPSIS
/* #include <percentm.h>
/* DESCRIPTION
/* .nf
/*
* External interface.
*/
extern char *percentm(const char *, int);
/* HISTORY
/* .ad
/* .fi
/* A percentm() routine appears in the TCP Wrapper software
/* by Wietse Venema.
/* 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
/*--*/
#endif

View File

@ -723,6 +723,21 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
RESTORE_SAVED_EUGID();
}
/* post_accept_init - announce our protocol */
static void post_accept_init(VSTREAM *stream, char *unused_name,
char **unused_argv, HTABLE *unused_table)
{
/*
* Announce the protocol.
*/
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_VERIFY),
ATTR_TYPE_END);
(void) vstream_fflush(stream);
}
MAIL_VERSION_STAMP_DECLARE;
/* main - pass control to the multi-threaded skeleton */
@ -754,6 +769,7 @@ int main(int argc, char **argv)
CA_MAIL_SERVER_TIME_TABLE(time_table),
CA_MAIL_SERVER_PRE_INIT(pre_jail_init),
CA_MAIL_SERVER_POST_INIT(post_jail_init),
CA_MAIL_SERVER_POST_ACCEPT(post_accept_init),
CA_MAIL_SERVER_SOLITARY,
CA_MAIL_SERVER_EXIT(verify_dump),
0);