Bugfix: the Milter client did not replace the Postfix-specific
form for unknown host names by the Sendmail-specific form.
File: milter/milter8.c.
+
+ Cleanup: when a cleanup milter reports a problem don't log
+ generic "4.3.0 Sevice unavailable", but log the text for
+ the actual error. File: cleanup/cleanup_milter.c.
+
+20080104
+
+ Workaround: minor change to the Dovecot AUTH request to
+ prevent dovecot-auth memory wastage. Timo Sirainen. File:
+ xsasl/xsasl_dovecot_server.c.
+
+20070807
+
+ Feature (experimental release only): new "pass" service
+ type (in addition to "inet", "unix" and "fifo"). The "pass"
+ service type supports front-end daemons that accept all
+ inbound connections and that permit only well-behaved clients
+ to talk to the MTA. This service type had been sitting in
+ the master daemon for years but was disabled by default.
+ Files: util/upass_connect.c, util/upass_trigger.c.
The mail_release_date configuration parameter (format: yyyymmdd)
specifies the release date of a stable release or snapshot release.
+Major changes with Postfix snapshot 20080107
+============================================
+
+New "pass" service type in master.cf. Written years ago, this
+allows a front-end daemon to accept all connections from the network,
+and forward only those from well-behaved clients to Postfix. Since
+this uses file descriptor passing, it imposes no overhead once a
+connection is handed over to Postfix. This is available in the
+experimental release only. See master(5) for a few details.
+
Incompatibility with Postfix snapshot 20071224
==============================================
Wish list:
- Milter client: send [ipaddress] instead of "unknown".
-
- The cleanup server should report "file too large" milter
- errors as permanent errors.
+ Consolidate duplicated code in {inet,unix,upass}_trigger.c.
In the SMTP client, handle 421 replies in smtp_loop() by
having the input function raise a flag after detecting 421
trolled with the <b><a href="postconf.5.html#queue_directory">queue_directory</a></b> configura-
tion parameter in <a href="postconf.5.html">main.cf</a>).
+ <b>pass</b> The service listens on a UNIX-domain socket,
+ receives one open connection (file descrip-
+ tor passing) per connection request, and is
+ accessible to local clients only.
+
+ This feature is not part of the stable Post-
+ fix release.
+
+ The service name is a pathname relative to
+ the Postfix queue directory (pathname con-
+ trolled with the <b><a href="postconf.5.html#queue_directory">queue_directory</a></b> configura-
+ tion parameter in <a href="postconf.5.html">main.cf</a>).
+
<b>Private (default: y)</b>
- Whether or not access is restricted to the mail
- system. Internet (type <b>inet</b>) services can't be
+ Whether or not access is restricted to the mail
+ system. Internet (type <b>inet</b>) services can't be
private.
<b>Unprivileged (default: y)</b>
Whether the service runs with root privileges or as
- the owner of the Postfix system (the owner name is
+ the owner of the Postfix system (the owner name is
controlled by the <b><a href="postconf.5.html#mail_owner">mail_owner</a></b> configuration variable
in the <a href="postconf.5.html">main.cf</a> file).
- The <a href="local.8.html"><b>local</b>(8)</a>, <a href="pipe.8.html"><b>pipe</b>(8)</a>, <a href="spawn.8.html"><b>spawn</b>(8)</a>, and <a href="virtual.8.html"><b>virtual</b>(8)</a>
+ The <a href="local.8.html"><b>local</b>(8)</a>, <a href="pipe.8.html"><b>pipe</b>(8)</a>, <a href="spawn.8.html"><b>spawn</b>(8)</a>, and <a href="virtual.8.html"><b>virtual</b>(8)</a>
daemons require privileges.
<b>Chroot (default: y)</b>
- Whether or not the service runs chrooted to the
+ Whether or not the service runs chrooted to the
mail queue directory (pathname is controlled by the
- <b><a href="postconf.5.html#queue_directory">queue_directory</a></b> configuration variable in the
+ <b><a href="postconf.5.html#queue_directory">queue_directory</a></b> configuration variable in the
<a href="postconf.5.html">main.cf</a> file).
Chroot should not be used with the <a href="local.8.html"><b>local</b>(8)</a>,
- <a href="pipe.8.html"><b>pipe</b>(8)</a>, <a href="spawn.8.html"><b>spawn</b>(8)</a>, and <a href="virtual.8.html"><b>virtual</b>(8)</a> daemons.
- Although the <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server can run chrooted,
+ <a href="pipe.8.html"><b>pipe</b>(8)</a>, <a href="spawn.8.html"><b>spawn</b>(8)</a>, and <a href="virtual.8.html"><b>virtual</b>(8)</a> daemons.
+ Although the <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server can run chrooted,
doing so defeats most of the purpose of having that
service in the first place.
The files in the examples/chroot-setup subdirectory
of the Postfix source archive show set up a Postfix
- chroot environment on a variety of systems. See
- also <a href="BASIC_CONFIGURATION_README.html">BASIC_CONFIGURATION_README</a> for issues related
+ chroot environment on a variety of systems. See
+ also <a href="BASIC_CONFIGURATION_README.html">BASIC_CONFIGURATION_README</a> for issues related
to running daemons chrooted.
<b>Wake up time (default: 0)</b>
- Automatically wake up the named service after the
- specified number of seconds. The wake up is imple-
- mented by connecting to the service and sending a
- wake up request. A ? at the end of the wake-up
- time field requests that no wake up events be sent
+ Automatically wake up the named service after the
+ specified number of seconds. The wake up is imple-
+ mented by connecting to the service and sending a
+ wake up request. A ? at the end of the wake-up
+ time field requests that no wake up events be sent
before the first time a service is used. Specify 0
for no automatic wake up.
a wake up timer.
<b>Process limit (default: $<a href="postconf.5.html#default_process_limit">default_process_limit</a>)</b>
- The maximum number of processes that may execute
+ The maximum number of processes that may execute
this service simultaneously. Specify 0 for no
process count limit.
NOTE: Some Postfix services must be configured as a
- single-process service (for example, <a href="qmgr.8.html"><b>qmgr</b>(8)</a>) and
- some services must be configured with no process
+ single-process service (for example, <a href="qmgr.8.html"><b>qmgr</b>(8)</a>) and
+ some services must be configured with no process
limit (for example, <a href="cleanup.8.html"><b>cleanup</b>(8)</a>). These limits must
not be changed.
<b>Command name + arguments</b>
- The command to be executed. Characters that are
- special to the shell such as ">" or "|" have no
- special meaning here, and quotes cannot be used to
+ The command to be executed. Characters that are
+ special to the shell such as ">" or "|" have no
+ special meaning here, and quotes cannot be used to
protect arguments containing whitespace.
- The command name is relative to the Postfix daemon
+ The command name is relative to the Postfix daemon
directory (pathname is controlled by the <b><a href="postconf.5.html#daemon_directory">dae</a>-</b>
<b><a href="postconf.5.html#daemon_directory">mon_directory</a></b> configuration variable).
- The command argument syntax for specific commands
- is specified in the respective daemon manual page.
+ The command argument syntax for specific commands
+ is specified in the respective daemon manual page.
- The following command-line options have the same
+ The following command-line options have the same
effect for all daemon programs:
- <b>-D</b> Run the daemon under control by the command
+ <b>-D</b> Run the daemon under control by the command
specified with the <b><a href="postconf.5.html#debugger_command">debugger_command</a></b> variable
in the <a href="postconf.5.html">main.cf</a> configuration file. See
<a href="DEBUG_README.html">DEBUG_README</a> for hints and tips.
<b>-o</b> <i>name</i>=<i>value</i>
Override the named <a href="postconf.5.html">main.cf</a> configuration
- parameter. The parameter value can refer to
+ parameter. The parameter value can refer to
other parameters as <i>$name</i> etc., just like in
<a href="postconf.5.html">main.cf</a>. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for syntax.
NOTE 1: do not specify whitespace around the
- "=". In parameter values, either avoid
+ "=". In parameter values, either avoid
whitespace altogether, use commas instead of
- spaces, or consider overrides like "-o
- name=$override_parameter" with $over-
+ spaces, or consider overrides like "-o
+ name=$override_parameter" with $over-
ride_parameter set in <a href="postconf.5.html">main.cf</a>.
- NOTE 2: Over-zealous use of parameter over-
- rides makes the Postfix configuration hard
- to understand and maintain. At a certain
- point, it might be easier to configure mul-
- tiple instances of Postfix, instead of con-
+ NOTE 2: Over-zealous use of parameter over-
+ rides makes the Postfix configuration hard
+ to understand and maintain. At a certain
+ point, it might be easier to configure mul-
+ tiple instances of Postfix, instead of con-
figuring multiple personalities via mas-
ter.cf.
- <b>-v</b> Increase the verbose logging level. Specify
+ <b>-v</b> Increase the verbose logging level. Specify
multiple <b>-v</b> options to make a Postfix daemon
process increasingly verbose.
<a href="DEBUG_README.html">DEBUG_README</a>, Postfix debugging
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
The service listens on a FIFO (named pipe) and is accessible
for local clients only.
+The service name is a pathname relative to the Postfix
+queue directory (pathname controlled with the \fBqueue_directory\fR
+configuration parameter in main.cf).
+.IP \fBpass\fR
+The service listens on a UNIX-domain socket, receives one
+open connection (file descriptor passing) per connection
+request, and is accessible to local clients only.
+
+This feature is not part of the stable Postfix release.
+
The service name is a pathname relative to the Postfix
queue directory (pathname controlled with the \fBqueue_directory\fR
configuration parameter in main.cf).
# The service name is a pathname relative to the Postfix
# queue directory (pathname controlled with the \fBqueue_directory\fR
# configuration parameter in main.cf).
+# .IP \fBpass\fR
+# The service listens on a UNIX-domain socket, receives one
+# open connection (file descriptor passing) per connection
+# request, and is accessible to local clients only.
+#
+# This feature is not part of the stable Postfix release.
+#
+# The service name is a pathname relative to the Postfix
+# queue directory (pathname controlled with the \fBqueue_directory\fR
+# configuration parameter in main.cf).
# .RE
# .IP "\fBPrivate (default: y)\fR"
# Whether or not access is restricted to the mail system.
const char *client_port; /* real or ersatz client */
VSTRING *milter_ext_from; /* externalized sender */
VSTRING *milter_ext_rcpt; /* externalized recipient */
+ VSTRING *milter_err_text; /* milter call-back reply */
/*
* Support for Milter body replacement requests.
static const char *cleanup_milter_error(CLEANUP_STATE *state, int err)
{
const char *myname = "cleanup_milter_error";
+ CLEANUP_STAT_DETAIL *dp;
/*
* For consistency with error reporting within the milter infrastructure,
cleanup_milter_set_error(state, err);
else if (CLEANUP_OUT_OK(state))
msg_panic("%s: missing errno to error flag mapping", myname);
- return ("451 4.3.0 Server internal error");
+ if (state->milter_err_text == 0)
+ state->milter_err_text = vstring_alloc(50);
+ dp = cleanup_stat_detail(state->errs);
+ return (STR(vstring_sprintf(state->milter_err_text,
+ "%d %s %s", dp->smtp, dp->dsn, dp->text)));
}
/* cleanup_add_header - append message header */
state->client_port = 0;
state->milter_ext_from = 0;
state->milter_ext_rcpt = 0;
+ state->milter_err_text = 0;
state->free_regions = state->body_regions = state->curr_body_region = 0;
return (state);
}
vstring_free(state->milter_ext_from);
if (state->milter_ext_rcpt)
vstring_free(state->milter_ext_rcpt);
+ if (state->milter_err_text)
+ vstring_free(state->milter_err_text);
cleanup_region_done(state);
myfree((char *) state);
}
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20071229"
+#define MAIL_RELEASE_DATE "20080107"
#define MAIL_VERSION_NUMBER "2.5"
#ifdef SNAPSHOT
int wakeup_time; /* wakeup interval */
int *listen_fd; /* incoming requests */
int listen_fd_count; /* nr of descriptors */
-#ifdef MASTER_SERV_TYPE_PASS
- struct PASS_INFO *pass_info; /* descriptor passing state */
-#endif
union {
struct {
char *port; /* inet listen port */
#define MASTER_SERV_TYPE_UNIX 1 /* AF_UNIX domain socket */
#define MASTER_SERV_TYPE_INET 2 /* AF_INET domain socket */
#define MASTER_SERV_TYPE_FIFO 3 /* fifo (named pipe) */
-/*#define MASTER_SERV_TYPE_PASS 4 /* AF_UNIX domain socket */
+#ifdef SNAPSHOT /* see also master_proto.h */
+#define MASTER_SERV_TYPE_PASS 4 /* AF_UNIX domain socket */
+#endif
/*
* Default process management policy values. This is only the bare minimum.
set_eugid(var_owner_uid, var_owner_gid);
serv->listen_fd[0] =
PASS_LISTEN(serv->name, serv->max_proc > var_proc_limit ?
- serv->max_proc : var_proc_limit, NON_BLOCKING,
- &(serv->pass_info));
+ serv->max_proc : var_proc_limit, NON_BLOCKING);
close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
set_ugid(getuid(), getgid());
break;
* listener. The 4.4BSD shutdown(2) man page promises an ENOTCONN error
* when shutdown(2) is applied to a socket that is not connected.
*/
-#ifdef MASTER_SERV_TYPE_PASS
- if (serv->type == MASTER_SERV_TYPE_PASS)
- PASS_SHUTDOWN(&(serv->pass_info));
-#endif
for (n = 0; n < serv->listen_fd_count; n++) {
if (close(serv->listen_fd[n]) < 0)
msg_warn("%s: close listener socket %d: %m",
#define MASTER_XPORT_NAME_UNIX "unix" /* local IPC */
#define MASTER_XPORT_NAME_FIFO "fifo" /* local IPC */
#define MASTER_XPORT_NAME_INET "inet" /* non-local IPC */
-/*#define MASTER_XPORT_NAME_PASS "pass" /* local IPC */
+#ifdef SNAPSHOT /* see also master.h */
+#define MASTER_XPORT_NAME_PASS "pass" /* local IPC */
+#endif
/*
* Format of a status message sent by a child process to the process
break;
#ifdef MASTER_SERV_TYPE_PASS
case MASTER_SERV_TYPE_PASS:
- /* Can't send data to a service that expects descriptors. */
- status = 0;
+ status = PASS_TRIGGER(serv->name, &wakeup, sizeof(wakeup), BRIEFLY);
break;
#endif
username.c valid_hostname.c vbuf.c vbuf_print.c vstream.c \
vstream_popen.c vstring.c vstring_vstream.c watchdog.c writable.c \
write_buf.c write_wait.c sane_basename.c format_tv.c allspace.c \
- allascii.c load_file.c killme_after.c vstream_tweak.c
+ allascii.c load_file.c killme_after.c vstream_tweak.c upass_connect.c \
+ upass_listen.c upass_trigger.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
username.o valid_hostname.o vbuf.o vbuf_print.o vstream.o \
vstream_popen.o vstring.o vstring_vstream.o watchdog.o writable.o \
write_buf.o write_wait.o sane_basename.o format_tv.o allspace.o \
- allascii.o load_file.o killme_after.o vstream_tweak.o
+ allascii.o load_file.o killme_after.o vstream_tweak.o upass_connect.o \
+ upass_listen.o upass_trigger.o
HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
unsafe.o: safe.h
unsafe.o: sys_defs.h
unsafe.o: unsafe.c
+upass_connect.o: connect.h
+upass_connect.o: events.h
+upass_connect.o: iostuff.h
+upass_connect.o: msg.h
+upass_connect.o: mymalloc.h
+upass_connect.o: sane_connect.h
+upass_connect.o: sane_socketpair.h
+upass_connect.o: sys_defs.h
+upass_connect.o: timed_connect.h
+upass_connect.o: upass_connect.c
upass_listen.o: iostuff.h
upass_listen.o: listen.h
upass_listen.o: msg.h
upass_listen.o: sane_accept.h
upass_listen.o: sys_defs.h
upass_listen.o: upass_listen.c
+upass_trigger.o: connect.h
+upass_trigger.o: events.h
+upass_trigger.o: iostuff.h
+upass_trigger.o: msg.h
+upass_trigger.o: mymalloc.h
+upass_trigger.o: sys_defs.h
+upass_trigger.o: trigger.h
+upass_trigger.o: upass_trigger.c
uppercase.o: stringops.h
uppercase.o: sys_defs.h
uppercase.o: uppercase.c
extern int unix_connect(const char *, int, int);
extern int inet_connect(const char *, int, int);
extern int stream_connect(const char *, int, int);
+extern int upass_connect(const char *, int, int);
/* LICENSE
/* .ad
extern int fifo_listen(const char *, int, int);
extern int stream_listen(const char *, int, int);
-#define upass_listen(path, mode, log) fifo_listen((path), (mode), (log))
+#define upass_listen(path, mode, log) unix_listen((path), (mode), (log))
extern int inet_accept(int);
extern int unix_accept(int);
#define LOCAL_RECV_FD unix_recv_fd
#endif
+#ifndef PASS_LISTEN
+#define PASS_LISTEN upass_listen
+#define PASS_ACCEPT upass_accept
+#define PASS_TRIGGER upass_trigger
+#endif
+
#if !defined (HAVE_SYS_NDIR_H) && !defined (HAVE_SYS_DIR_H) \
&& !defined (HAVE_NDIR_H)
#define HAVE_DIRENT_H
extern int inet_trigger(const char *, const char *, ssize_t, int);
extern int fifo_trigger(const char *, const char *, ssize_t, int);
extern int stream_trigger(const char *, const char *, ssize_t, int);
+extern int upass_trigger(const char *, const char *, ssize_t, int);
/* LICENSE
/* .ad
* Create a client socket.
*/
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
- msg_fatal("socket: %m");
+ return (-1);
/*
* Timed connect.
--- /dev/null
+/*++
+/* NAME
+/* upass_connect 3
+/* SUMMARY
+/* connect to UNIX-domain file descriptor listener
+/* SYNOPSIS
+/* #include <connect.h>
+/*
+/* int upass_connect(addr, block_mode, timeout)
+/* const char *addr;
+/* int block_mode;
+/* int timeout;
+/* DESCRIPTION
+/* upass_connect() connects to a file descriptor listener in
+/* the UNIX domain at the specified address, sends one half
+/* of a socketpair to the listener, and returns the other half
+/* to the caller.
+/*
+/* The file descriptor transporting connection is closed by
+/* a background thread. Some kernels might otherwise discard
+/* the descriptor before the server has received it.
+/*
+/* Arguments:
+/* .IP addr
+/* Null-terminated string with connection destination.
+/* .IP block_mode
+/* Either NON_BLOCKING for a non-blocking socket, or BLOCKING for
+/* blocking mode. This setting has no effect on the connection
+/* establishment process.
+/* .IP timeout
+/* Bounds the number of seconds that the operation may take. Specify
+/* a value <= 0 to disable the time limit.
+/* DIAGNOSTICS
+/* The result is -1 in case the connection could not be made.
+/* Fatal errors: other system call failures.
+/* 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 interfaces. */
+
+#include <sys_defs.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <iostuff.h>
+#include <sane_connect.h>
+#include <connect.h>
+#include <timed_connect.h>
+#include <events.h>
+#include <mymalloc.h>
+#include <sane_socketpair.h>
+
+ /*
+ * Workaround for hostile kernels that don't support graceful shutdown.
+ */
+struct upass_connect {
+ int fd;
+ char *service;
+};
+
+/* upass_connect_event - disconnect from peer */
+
+static void upass_connect_event(int event, char *context)
+{
+ struct upass_connect *up = (struct upass_connect *) context;
+ static const char *myname = "upass_connect_event";
+
+ /*
+ * Disconnect.
+ */
+ if (event == EVENT_TIME)
+ msg_warn("%s: read timeout for service %s", myname, up->service);
+ event_disable_readwrite(up->fd);
+ event_cancel_timer(upass_connect_event, context);
+ if (close(up->fd) < 0)
+ msg_warn("%s: close %s: %m", myname, up->service);
+ myfree(up->service);
+ myfree((char *) up);
+}
+
+/* upass_connect - connect to UNIX-domain file descriptor listener */
+
+int upass_connect(const char *addr, int block_mode, int timeout)
+{
+ struct upass_connect *up;
+ int pair[2];
+ int sock;
+
+ /*
+ * Connect.
+ */
+ if ((sock = unix_connect(addr, BLOCKING, timeout)) < 0)
+ return (-1);
+
+ /*
+ * Send one socket pair half to the server.
+ */
+#define OUR_HALF 0
+#define THEIR_HALF 1
+
+ if (sane_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) < 0) {
+ close(sock);
+ return (-1);
+ }
+ if (unix_send_fd(sock, pair[THEIR_HALF]) < 0) {
+ close(pair[THEIR_HALF]);
+ close(pair[OUR_HALF]);
+ close(sock);
+ return (-1);
+ }
+ close(pair[THEIR_HALF]);
+
+ /*
+ * Return the other socket pair half to the caller. Don't close the
+ * control socket just yet, but wait until the receiver closes it first.
+ * Otherwise, some hostile kernel might discard the socket that we just
+ * sent.
+ */
+ up = (struct upass_connect *) mymalloc(sizeof(*up));
+ up->fd = sock;
+ up->service = mystrdup(addr);
+ if (timeout > 0)
+ event_request_timer(upass_connect_event, (char *) up, timeout + 100);
+ event_enable_read(sock, upass_connect_event, (char *) up);
+ non_blocking(pair[OUR_HALF], block_mode);
+ return (pair[OUR_HALF]);
+}
--- /dev/null
+/*++
+/* NAME
+/* upass_trigger 3
+/* SUMMARY
+/* wakeup UNIX-domain file descriptor listener
+/* SYNOPSIS
+/* #include <trigger.h>
+/*
+/* int upass_trigger(service, buf, len, timeout)
+/* const char *service;
+/* const char *buf;
+/* ssize_t len;
+/* int timeout;
+/* DESCRIPTION
+/* upass_trigger() wakes up the named UNIX-domain server by sending
+/* a brief connection to it and writing the named buffer.
+/*
+/* The connection is closed by a background thread. Some kernels
+/* cannot handle client-side disconnect before the server has
+/* received the message.
+/*
+/* Arguments:
+/* .IP service
+/* Name of the communication endpoint.
+/* .IP buf
+/* Address of data to be written.
+/* .IP len
+/* Amount of data to be written.
+/* .IP timeout
+/* Deadline in seconds. Specify a value <= 0 to disable
+/* the time limit.
+/* DIAGNOSTICS
+/* The result is zero in case of success, -1 in case of problems.
+/* SEE ALSO
+/* upass_connect(3), UNIX-domain client
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <connect.h>
+#include <iostuff.h>
+#include <mymalloc.h>
+#include <events.h>
+#include <trigger.h>
+
+struct upass_trigger {
+ int fd;
+ char *service;
+};
+
+/* upass_trigger_event - disconnect from peer */
+
+static void upass_trigger_event(int event, char *context)
+{
+ struct upass_trigger *up = (struct upass_trigger *) context;
+ static const char *myname = "upass_trigger_event";
+
+ /*
+ * Disconnect.
+ */
+ if (event == EVENT_TIME)
+ msg_warn("%s: read timeout for service %s", myname, up->service);
+ event_disable_readwrite(up->fd);
+ event_cancel_timer(upass_trigger_event, context);
+ if (close(up->fd) < 0)
+ msg_warn("%s: close %s: %m", myname, up->service);
+ myfree(up->service);
+ myfree((char *) up);
+}
+
+/* upass_trigger - wakeup UNIX-domain server */
+
+int upass_trigger(const char *service, const char *buf, ssize_t len, int timeout)
+{
+ const char *myname = "upass_trigger";
+ struct upass_trigger *up;
+ int fd;
+
+ if (msg_verbose > 1)
+ msg_info("%s: service %s", myname, service);
+
+ /*
+ * Connect...
+ */
+ if ((fd = upass_connect(service, BLOCKING, timeout)) < 0) {
+ if (msg_verbose)
+ msg_warn("%s: connect to %s: %m", myname, service);
+ return (-1);
+ }
+ close_on_exec(fd, CLOSE_ON_EXEC);
+
+ /*
+ * Stash away context.
+ */
+ up = (struct upass_trigger *) mymalloc(sizeof(*up));
+ up->fd = fd;
+ up->service = mystrdup(service);
+
+ /*
+ * Write the request...
+ */
+ if (write_buf(fd, buf, len, timeout) < 0
+ || write_buf(fd, "", 1, timeout) < 0)
+ if (msg_verbose)
+ msg_warn("%s: write to %s: %m", myname, service);
+
+ /*
+ * Wakeup when the peer disconnects, or when we lose patience.
+ */
+ if (timeout > 0)
+ event_request_timer(upass_trigger_event, (char *) up, timeout + 100);
+ event_enable_read(fd, upass_trigger_event, (char *) up);
+ return (0);
+}
/* send the request */
server->last_request_id = ++server->impl->request_id_counter;
vstream_fprintf(server->impl->sasl_stream,
- "AUTH\t%u\t%s\tservice=%s",
+ "AUTH\t%u\t%s\tservice=%s\tnologin",
server->last_request_id, sasl_method,
server->service);
if (init_response) {