5
/* Postfix delivery to external command
7
/* \fBpipe\fR [generic Postfix daemon options] command_attributes...
9
/* The \fBpipe\fR daemon processes requests from the Postfix queue
10
/* manager to deliver messages to external commands.
11
/* This program expects to be run from the \fBmaster\fR(8) process
14
/* Message attributes such as sender address, recipient address and
15
/* next-hop host name can be specified as command-line macros that are
16
/* expanded before the external command is executed.
18
/* The \fBpipe\fR daemon updates queue files and marks recipients
19
/* as finished, or it informs the queue manager that delivery should
20
/* be tried again at a later time. Delivery status reports are sent
21
/* to the \fBbounce\fR(8), \fBdefer\fR(8) or \fBtrace\fR(8) daemon as
23
/* SINGLE-RECIPIENT DELIVERY
26
/* Some external commands cannot handle more than one recipient
27
/* per delivery request. Examples of such transports are pagers,
28
/* fax machines, and so on.
30
/* To prevent Postfix from sending multiple recipients per delivery
34
/* \fItransport\fB_destination_recipient_limit = 1\fR
36
/* in the Postfix \fBmain.cf\fR file, where \fItransport\fR
37
/* is the name in the first column of the Postfix \fBmaster.cf\fR
38
/* entry for the pipe-based delivery transport.
39
/* COMMAND ATTRIBUTE SYNTAX
42
/* The external command attributes are given in the \fBmaster.cf\fR
43
/* file at the end of a service definition. The syntax is as follows:
44
/* .IP "\fBflags=BDFORhqu.>\fR (optional)"
45
/* Optional message processing flags. By default, a message is
49
/* Append a blank line at the end of each message. This is required
50
/* by some mail user agents that recognize "\fBFrom \fR" lines only
51
/* when preceded by a blank line.
53
/* Prepend a "\fBDelivered-To: \fIrecipient\fR" message header with the
54
/* envelope recipient address. Note: for this to work, the
55
/* \fItransport\fB_destination_recipient_limit\fR must be 1.
57
/* Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
58
/* the message content.
59
/* This is expected by, for example, \fBUUCP\fR software.
61
/* Prepend an "\fBX-Original-To: \fIrecipient\fR" message header
62
/* with the recipient address as given to Postfix. Note: for this to
63
/* work, the \fItransport\fB_destination_recipient_limit\fR must be 1.
65
/* Prepend a \fBReturn-Path:\fR message header with the envelope sender
68
/* Fold the command-line \fB$recipient\fR domain name and \fB$nexthop\fR
69
/* host name to lower case.
70
/* This is recommended for delivery via \fBUUCP\fR.
72
/* Quote white space and other special characters in the command-line
73
/* \fB$sender\fR and \fB$recipient\fR address localparts (text to the
74
/* left of the right-most \fB@\fR character), according to an 8-bit
75
/* transparent version of RFC 822.
76
/* This is recommended for delivery via \fBUUCP\fR or \fBBSMTP\fR.
78
/* The result is compatible with the address parsing of command-line
79
/* recipients by the Postfix \fBsendmail\fR mail submission command.
81
/* The \fBq\fR flag affects only entire addresses, not the partial
82
/* address information from the \fB$user\fR, \fB$extension\fR or
83
/* \fB$mailbox\fR command-line macros.
85
/* Fold the command-line \fB$recipient\fR address localpart (text to
86
/* the left of the right-most \fB@\fR character) to lower case.
87
/* This is recommended for delivery via \fBUUCP\fR.
89
/* Prepend \fB.\fR to lines starting with "\fB.\fR". This is needed
90
/* by, for example, \fBBSMTP\fR software.
92
/* Prepend \fB>\fR to lines starting with "\fBFrom \fR". This is expected
93
/* by, for example, \fBUUCP\fR software.
95
/* .IP "\fBuser\fR=\fIusername\fR (required)"
96
/* .IP "\fBuser\fR=\fIusername\fR:\fIgroupname\fR"
97
/* The external command is executed with the rights of the
98
/* specified \fIusername\fR. The software refuses to execute
99
/* commands with root privileges, or with the privileges of the
100
/* mail system owner. If \fIgroupname\fR is specified, the
101
/* corresponding group ID is used instead of the group ID of
103
/* .IP "\fBeol=string\fR (optional, default: \fB\en\fR)"
104
/* The output record delimiter. Typically one would use either
105
/* \fB\er\en\fR or \fB\en\fR. The usual C-style backslash escape
106
/* sequences are recognized: \fB\ea \eb \ef \en \er \et \ev
107
/* \e\fIoctal\fR and \fB\e\e\fR.
108
/* .IP "\fBsize\fR=\fIsize_limit\fR (optional)"
109
/* Messages greater in size than this limit (in bytes) will be bounced
110
/* back to the sender.
111
/* .IP "\fBargv\fR=\fIcommand\fR... (required)"
112
/* The command to be executed. This must be specified as the
113
/* last command attribute.
114
/* The command is executed directly, i.e. without interpretation of
115
/* shell meta characters by a shell command interpreter.
117
/* In the command argument vector, the following macros are recognized
118
/* and replaced with corresponding information from the Postfix queue
119
/* manager delivery request:
121
/* .IP \fB${\fBextension\fR}\fR
122
/* This macro expands to the extension part of a recipient address.
123
/* For example, with an address \fIuser+foo@domain\fR the extension is
126
/* A command-line argument that contains \fB${\fBextension\fR}\fR expands
127
/* into as many command-line arguments as there are recipients.
129
/* This information is modified by the \fBu\fR flag for case folding.
130
/* .IP \fB${\fBmailbox\fR}\fR
131
/* This macro expands to the complete local part of a recipient address.
132
/* For example, with an address \fIuser+foo@domain\fR the mailbox is
135
/* A command-line argument that contains \fB${\fBmailbox\fR}\fR
136
/* expands into as many command-line arguments as there are recipients.
138
/* This information is modified by the \fBu\fR flag for case folding.
139
/* .IP \fB${\fBnexthop\fR}\fR
140
/* This macro expands to the next-hop hostname.
142
/* This information is modified by the \fBh\fR flag for case folding.
143
/* .IP \fB${\fBrecipient\fR}\fR
144
/* This macro expands to the complete recipient address.
146
/* A command-line argument that contains \fB${\fBrecipient\fR}\fR
147
/* expands into as many command-line arguments as there are recipients.
149
/* This information is modified by the \fBhqu\fR flags for quoting
151
/* .IP \fB${\fBsender\fR}\fR
152
/* This macro expands to the envelope sender address.
154
/* This information is modified by the \fBq\fR flag for quoting.
155
/* .IP \fB${\fBsize\fR}\fR
156
/* This macro expands to Postfix's idea of the message size, which
157
/* is an approximation of the size of the message as delivered.
158
/* .IP \fB${\fBuser\fR}\fR
159
/* This macro expands to the username part of a recipient address.
160
/* For example, with an address \fIuser+foo@domain\fR the username
161
/* part is \fIuser\fR.
163
/* A command-line argument that contains \fB${\fBuser\fR}\fR expands
164
/* into as many command-line arguments as there are recipients.
166
/* This information is modified by the \fBu\fR flag for case folding.
169
/* In addition to the form ${\fIname\fR}, the forms $\fIname\fR and
170
/* $(\fIname\fR) are also recognized. Specify \fB$$\fR where a single
171
/* \fB$\fR is wanted.
173
/* Command exit status codes are expected to
174
/* follow the conventions defined in <\fBsysexits.h\fR>.
176
/* Problems and transactions are logged to \fBsyslogd\fR(8).
177
/* Corrupted message files are marked so that the queue manager
178
/* can move them to the \fBcorrupt\fR queue for further inspection.
182
/* This program needs a dual personality 1) to access the private
183
/* Postfix queue and IPC mechanisms, and 2) to execute external
184
/* commands as the specified user. It is therefore security sensitive.
185
/* CONFIGURATION PARAMETERS
188
/* Changes to \fBmain.cf\fR are picked up automatically as pipe(8)
189
/* processes run for only a limited amount of time. Use the command
190
/* "\fBpostfix reload\fR" to speed up a change.
192
/* The text below provides only a parameter summary. See
193
/* postconf(5) for more details including examples.
194
/* RESOURCE AND RATE CONTROLS
197
/* In the text below, \fItransport\fR is the first field in a
198
/* \fBmaster.cf\fR entry.
199
/* .IP "\fItransport\fB_destination_concurrency_limit ($default_destination_concurrency_limit)\fR"
200
/* Limit the number of parallel deliveries to the same destination,
201
/* for delivery via the named \fItransport\fR.
202
/* The limit is enforced by the Postfix queue manager.
203
/* .IP "\fItransport\fB_destination_recipient_limit ($default_destination_recipient_limit)\fR"
204
/* Limit the number of recipients per message delivery, for delivery
205
/* via the named \fItransport\fR.
206
/* The limit is enforced by the Postfix queue manager.
207
/* .IP "\fItransport\fB_time_limit ($command_time_limit)\fR"
208
/* Limit the time for delivery to external command, for delivery via
209
/* the named \fItransport\fR.
210
/* The limit is enforced by the pipe delivery agent.
211
/* MISCELLANEOUS CONTROLS
214
/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
215
/* The default location of the Postfix main.cf and master.cf
216
/* configuration files.
217
/* .IP "\fBdaemon_timeout (18000s)\fR"
218
/* How much time a Postfix daemon process may take to handle a
219
/* request before it is terminated by a built-in watchdog timer.
220
/* .IP "\fBexport_environment (see 'postconf -d' output)\fR"
221
/* The list of environment variables that a Postfix process will export
222
/* to non-Postfix processes.
223
/* .IP "\fBipc_timeout (3600s)\fR"
224
/* The time limit for sending or receiving information over an internal
225
/* communication channel.
226
/* .IP "\fBmail_owner (postfix)\fR"
227
/* The UNIX system account that owns the Postfix queue and most Postfix
229
/* .IP "\fBmax_idle (100s)\fR"
230
/* The maximum amount of time that an idle Postfix daemon process
231
/* waits for the next service request before exiting.
232
/* .IP "\fBmax_use (100)\fR"
233
/* The maximal number of connection requests before a Postfix daemon
234
/* process terminates.
235
/* .IP "\fBprocess_id (read-only)\fR"
236
/* The process ID of a Postfix command or daemon process.
237
/* .IP "\fBprocess_name (read-only)\fR"
238
/* The process name of a Postfix command or daemon process.
239
/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
240
/* The location of the Postfix top-level queue directory.
241
/* .IP "\fBrecipient_delimiter (empty)\fR"
242
/* The separator between user names and address extensions (user+foo).
243
/* .IP "\fBsyslog_facility (mail)\fR"
244
/* The syslog facility of Postfix logging.
245
/* .IP "\fBsyslog_name (postfix)\fR"
246
/* The mail system name that is prepended to the process name in syslog
247
/* records, so that "smtpd" becomes, for example, "postfix/smtpd".
249
/* qmgr(8), queue manager
250
/* bounce(8), delivery status reports
251
/* postconf(5), configuration parameters
252
/* master(8), process manager
253
/* syslogd(8), system logging
257
/* The Secure Mailer license must be distributed with this software.
260
/* IBM T.J. Watson Research
262
/* Yorktown Heights, NY 10598, USA
265
/* System library. */
267
#include <sys_defs.h>
276
#ifdef STRCASECMP_IN_STRINGS_H
280
/* Utility library. */
289
#include <mymalloc.h>
290
#include <mac_parse.h>
291
#include <set_eugid.h>
292
#include <split_at.h>
293
#include <stringops.h>
295
/* Global library. */
297
#include <recipient_list.h>
298
#include <deliver_request.h>
299
#include <mail_params.h>
300
#include <mail_conf.h>
303
#include <deliver_completed.h>
305
#include <pipe_command.h>
306
#include <mail_copy.h>
307
#include <mail_addr.h>
308
#include <canon_addr.h>
309
#include <split_addr.h>
311
#include <quote_822_local.h>
312
#include <flush_clnt.h>
314
/* Single server skeleton. */
316
#include <mail_server.h>
318
/* Application-specific. */
321
* The mini symbol table name and keys used for expanding macros in
322
* command-line arguments.
324
* XXX Update the parse_callback() routine when something gets added here,
325
* even when the macro is not recipient dependent.
327
#define PIPE_DICT_TABLE "pipe_command" /* table name */
328
#define PIPE_DICT_NEXTHOP "nexthop" /* key */
329
#define PIPE_DICT_RCPT "recipient" /* key */
330
#define PIPE_DICT_SENDER "sender"/* key */
331
#define PIPE_DICT_USER "user" /* key */
332
#define PIPE_DICT_EXTENSION "extension" /* key */
333
#define PIPE_DICT_MAILBOX "mailbox" /* key */
334
#define PIPE_DICT_SIZE "size" /* key */
337
* Flags used to pass back the type of special parameter found by
340
#define PIPE_FLAG_RCPT (1<<0)
341
#define PIPE_FLAG_USER (1<<1)
342
#define PIPE_FLAG_EXTENSION (1<<2)
343
#define PIPE_FLAG_MAILBOX (1<<3)
346
* Additional flags. These are colocated with mail_copy() flags. Allow some
347
* space for extension of the mail_copy() interface.
349
#define PIPE_OPT_FOLD_USER (1<<16)
350
#define PIPE_OPT_FOLD_HOST (1<<17)
351
#define PIPE_OPT_QUOTE_LOCAL (1<<18)
353
#define PIPE_OPT_FOLD_FLAGS (PIPE_OPT_FOLD_USER | PIPE_OPT_FOLD_HOST)
356
* Tunable parameters. Values are taken from the config file, after
357
* prepending the service name to _name, and so on.
359
int var_command_maxtime; /* system-wide */
362
* For convenience. Instead of passing around lists of parameters, bundle
363
* them up in convenient structures.
367
* Structure for service-specific configuration parameters.
370
int time_limit; /* per-service time limit */
374
* Structure for command-line parameters.
377
char **command; /* argument vector */
378
uid_t uid; /* command privileges */
379
gid_t gid; /* command privileges */
380
int flags; /* mail_copy() flags */
381
VSTRING *eol; /* output record delimiter */
382
off_t size_limit; /* max size in bytes we will accept */
386
* Structure for command-line parameter macro expansion.
389
const char *service; /* for warnings */
390
int expand_flag; /* callback result */
394
* Silly little macros.
396
#define STR vstring_str
398
/* parse_callback - callback for mac_parse() */
400
static int parse_callback(int type, VSTRING *buf, char *context)
402
PIPE_STATE *state = (PIPE_STATE *) context;
407
static struct cmd_flags cmd_flags[] = {
408
PIPE_DICT_NEXTHOP, 0,
409
PIPE_DICT_RCPT, PIPE_FLAG_RCPT,
411
PIPE_DICT_USER, PIPE_FLAG_USER,
412
PIPE_DICT_EXTENSION, PIPE_FLAG_EXTENSION,
413
PIPE_DICT_MAILBOX, PIPE_FLAG_MAILBOX,
420
* See if this command-line argument references a special macro.
422
if (type == MAC_PARSE_VARNAME) {
423
for (p = cmd_flags; /* see below */ ; p++) {
425
msg_warn("file %s/%s: service %s: unknown macro name: \"%s\"",
426
var_config_dir, MASTER_CONF_FILE,
427
state->service, vstring_str(buf));
428
return (MAC_PARSE_ERROR);
429
} else if (strcmp(vstring_str(buf), p->name) == 0) {
430
state->expand_flag |= p->flags;
438
/* morph_recipient - morph a recipient address */
440
static void morph_recipient(VSTRING *buf, const char *address, int flags)
445
* Quote the recipient address as appropriate.
447
if (flags & PIPE_OPT_QUOTE_LOCAL)
448
quote_822_local(buf, address);
450
vstring_strcpy(buf, address);
453
* Fold the recipient address as appropriate.
455
switch (flags & PIPE_OPT_FOLD_FLAGS) {
456
case PIPE_OPT_FOLD_HOST:
457
if ((cp = strrchr(STR(buf), '@')) != 0)
460
case PIPE_OPT_FOLD_USER:
461
if ((cp = strrchr(STR(buf), '@')) != 0) {
467
case PIPE_OPT_FOLD_USER | PIPE_OPT_FOLD_HOST:
473
/* expand_argv - expand macros in the argument vector */
475
static ARGV *expand_argv(const char *service, char **argv,
476
RECIPIENT_LIST *rcpt_list, int flags)
478
VSTRING *buf = vstring_alloc(100);
486
* This appears to be simple operation (replace $name by its expansion).
487
* However, it becomes complex because a command-line argument that
488
* references $recipient must expand to as many command-line arguments as
489
* there are recipients (that's wat programs called by sendmail expect).
490
* So we parse each command-line argument, and depending on what we find,
491
* we either expand the argument just once, or we expand it once for each
492
* recipient. In either case we end up parsing the command-line argument
493
* twice. The amount of CPU time wasted will be negligible.
495
* Note: we can't use recursive macro expansion here, because recursion
496
* would screw up mail addresses that contain $ characters.
499
#define EARLY_RETURN(x) { argv_free(result); vstring_free(buf); return (x); }
501
result = argv_alloc(1);
502
for (cpp = argv; *cpp; cpp++) {
503
state.service = service;
504
state.expand_flag = 0;
505
if (mac_parse(*cpp, parse_callback, (char *) &state) & MAC_PARSE_ERROR)
507
if (state.expand_flag == 0) { /* no $recipient etc. */
508
argv_add(result, dict_eval(PIPE_DICT_TABLE, *cpp, NO), ARGV_END);
509
} else { /* contains $recipient etc. */
510
for (i = 0; i < rcpt_list->len; i++) {
513
* This argument contains $recipient.
515
if (state.expand_flag & PIPE_FLAG_RCPT) {
516
morph_recipient(buf, rcpt_list->info[i].address, flags);
517
dict_update(PIPE_DICT_TABLE, PIPE_DICT_RCPT, STR(buf));
521
* This argument contains $user. Extract the plain user name.
522
* Either anything to the left of the extension delimiter or,
523
* in absence of the latter, anything to the left of the
526
* Beware: if the user name is blank (e.g. +user@host), the
527
* argument is suppressed. This is necessary to allow for
528
* cyrus bulletin-board (global mailbox) delivery. XXX But,
529
* skipping empty user parts will also prevent other
530
* expansions of this specific command-line argument.
532
if (state.expand_flag & PIPE_FLAG_USER) {
533
morph_recipient(buf, rcpt_list->info[i].address,
534
flags & PIPE_OPT_FOLD_FLAGS);
535
if (split_at_right(STR(buf), '@') == 0)
536
msg_warn("no @ in recipient address: %s",
537
rcpt_list->info[i].address);
539
split_addr(STR(buf), *var_rcpt_delim);
542
dict_update(PIPE_DICT_TABLE, PIPE_DICT_USER, STR(buf));
546
* This argument contains $extension. Extract the recipient
547
* extension: anything between the leftmost extension
548
* delimiter and the rightmost @. The extension may be blank.
550
if (state.expand_flag & PIPE_FLAG_EXTENSION) {
551
morph_recipient(buf, rcpt_list->info[i].address,
552
flags & PIPE_OPT_FOLD_FLAGS);
553
if (split_at_right(STR(buf), '@') == 0)
554
msg_warn("no @ in recipient address: %s",
555
rcpt_list->info[i].address);
556
if (*var_rcpt_delim == 0
557
|| (ext = split_addr(STR(buf), *var_rcpt_delim)) == 0)
558
ext = ""; /* insert null arg */
559
dict_update(PIPE_DICT_TABLE, PIPE_DICT_EXTENSION, ext);
563
* This argument contains $mailbox. Extract the mailbox name:
564
* anything to the left of the rightmost @.
566
if (state.expand_flag & PIPE_FLAG_MAILBOX) {
567
morph_recipient(buf, rcpt_list->info[i].address,
568
flags & PIPE_OPT_FOLD_FLAGS);
569
if (split_at_right(STR(buf), '@') == 0)
570
msg_warn("no @ in recipient address: %s",
571
rcpt_list->info[i].address);
572
dict_update(PIPE_DICT_TABLE, PIPE_DICT_MAILBOX, STR(buf));
578
argv_add(result, dict_eval(PIPE_DICT_TABLE, *cpp, NO), ARGV_END);
582
argv_terminate(result);
587
/* get_service_params - get service-name dependent config information */
589
static void get_service_params(PIPE_PARAMS *config, char *service)
591
char *myname = "get_service_params";
594
* Figure out the command time limit for this transport.
597
get_mail_conf_int2(service, "_time_limit", var_command_maxtime, 1, 0);
600
* Give the poor tester a clue of what is going on.
603
msg_info("%s: time_limit %d", myname, config->time_limit);
606
/* get_service_attr - get command-line attributes */
608
static void get_service_attr(PIPE_ATTR *attr, char **argv)
610
char *myname = "get_service_attr";
613
char *user; /* user name */
614
char *group; /* group name */
615
char *size; /* max message size */
625
attr->eol = vstring_strcpy(vstring_alloc(1), "\n");
626
attr->size_limit = 0;
629
* Iterate over the command-line attribute list.
631
for ( /* void */ ; *argv != 0; argv++) {
636
if (strncasecmp("flags=", *argv, sizeof("flags=") - 1) == 0) {
637
for (cp = *argv + sizeof("flags=") - 1; *cp; cp++) {
640
attr->flags |= MAIL_COPY_BLANK;
643
attr->flags |= MAIL_COPY_DELIVERED;
646
attr->flags |= MAIL_COPY_FROM;
649
attr->flags |= MAIL_COPY_ORIG_RCPT;
652
attr->flags |= MAIL_COPY_RETURN_PATH;
655
attr->flags |= MAIL_COPY_DOT;
658
attr->flags |= MAIL_COPY_QUOTE;
661
attr->flags |= PIPE_OPT_FOLD_HOST;
664
attr->flags |= PIPE_OPT_QUOTE_LOCAL;
667
attr->flags |= PIPE_OPT_FOLD_USER;
670
msg_fatal("unknown flag: %c (ignored)", *cp);
677
* user=username[:groupname]
679
else if (strncasecmp("user=", *argv, sizeof("user=") - 1) == 0) {
680
user = *argv + sizeof("user=") - 1;
681
if ((group = split_at(user, ':')) != 0) /* XXX clobbers argv */
684
if ((pwd = getpwnam(user)) == 0)
685
msg_fatal("%s: unknown username: %s", myname, user);
686
attr->uid = pwd->pw_uid;
688
if ((grp = getgrnam(group)) == 0)
689
msg_fatal("%s: unknown group: %s", myname, group);
690
attr->gid = grp->gr_gid;
692
attr->gid = pwd->pw_gid;
699
else if (strncasecmp("eol=", *argv, sizeof("eol=") - 1) == 0) {
700
unescape(attr->eol, *argv + sizeof("eol=") - 1);
704
* size=max_message_size (in bytes)
706
else if (strncasecmp("size=", *argv, sizeof("size=") - 1) == 0) {
707
size = *argv + sizeof("size=") - 1;
708
if ((attr->size_limit = off_cvt_string(size)) < 0)
709
msg_fatal("%s: bad size= value: %s", myname, size);
715
else if (strncasecmp("argv=", *argv, sizeof("argv=") - 1) == 0) {
716
*argv += sizeof("argv=") - 1; /* XXX clobbers argv */
717
attr->command = argv;
725
msg_fatal("unknown attribute name: %s", *argv);
729
* Sanity checks. Verify that every member has an acceptable value.
732
msg_fatal("missing user= command-line attribute");
733
if (attr->command == 0)
734
msg_fatal("missing argv= command-line attribute");
736
msg_fatal("user= command-line attribute specifies root privileges");
737
if (attr->uid == var_owner_uid)
738
msg_fatal("user= command-line attribute specifies mail system owner %s",
741
msg_fatal("user= command-line attribute specifies privileged group id 0");
742
if (attr->gid == var_owner_gid)
743
msg_fatal("user= command-line attribute specifies mail system owner %s group id %ld",
744
var_mail_owner, (long) attr->gid);
747
* Give the poor tester a clue of what is going on.
750
msg_info("%s: uid %ld, gid %ld, flags %d, size %ld",
751
myname, (long) attr->uid, (long) attr->gid,
752
attr->flags, (long) attr->size_limit);
755
/* eval_command_status - do something with command completion status */
757
static int eval_command_status(int command_status, char *service,
758
DELIVER_REQUEST *request, VSTREAM *src,
767
* Depending on the result, bounce or defer the message, and mark the
768
* recipient as done where appropriate.
770
switch (command_status) {
772
for (n = 0; n < request->rcpt_list.len; n++) {
773
rcpt = request->rcpt_list.info + n;
774
status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
775
request->queue_id, rcpt->orig_addr,
776
rcpt->address, rcpt->offset, service,
777
request->arrival_time, "%s", request->nexthop);
778
if (status == 0 && (request->flags & DEL_REQ_FLAG_SUCCESS))
779
deliver_completed(src, rcpt->offset);
783
case PIPE_STAT_BOUNCE:
784
for (n = 0; n < request->rcpt_list.len; n++) {
785
rcpt = request->rcpt_list.info + n;
786
status = bounce_append(DEL_REQ_TRACE_FLAGS(request->flags),
787
request->queue_id, rcpt->orig_addr,
788
rcpt->address, rcpt->offset, service,
789
request->arrival_time, "%s", why);
791
deliver_completed(src, rcpt->offset);
795
case PIPE_STAT_DEFER:
796
for (n = 0; n < request->rcpt_list.len; n++) {
797
rcpt = request->rcpt_list.info + n;
798
result |= defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
799
request->queue_id, rcpt->orig_addr,
800
rcpt->address, rcpt->offset, service,
801
request->arrival_time, "%s", why);
804
case PIPE_STAT_CORRUPT:
805
result |= DEL_STAT_DEFER;
808
msg_panic("eval_command_status: bad status %d", command_status);
814
/* deliver_message - deliver message with extreme prejudice */
816
static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
818
char *myname = "deliver_message";
819
static PIPE_PARAMS conf;
820
static PIPE_ATTR attr;
821
RECIPIENT_LIST *rcpt_list = &request->rcpt_list;
822
VSTRING *why = vstring_alloc(100);
824
ARGV *expanded_argv = 0;
829
#define DELIVER_MSG_CLEANUP() { \
831
if (expanded_argv) argv_free(expanded_argv); \
835
msg_info("%s: from <%s>", myname, request->sender);
838
* First of all, replace an empty sender address by the mailer daemon
839
* address. The resolver already fixes empty recipient addresses.
841
* XXX Should sender and recipient be transformed into external (i.e.
842
* quoted) form? Problem is that the quoting rules are transport
843
* specific. Such information must evidently not be hard coded into
844
* Postfix, but would have to be provided in the form of lookup tables.
846
if (request->sender[0] == 0) {
847
buf = vstring_alloc(100);
848
canon_addr_internal(buf, MAIL_ADDR_MAIL_DAEMON);
849
myfree(request->sender);
850
request->sender = vstring_export(buf);
854
* Sanity checks. The get_service_params() and get_service_attr()
855
* routines also do some sanity checks. Look up service attributes and
856
* config information only once. This is safe since the information comes
857
* from a trusted source, not from the delivery request.
859
if (request->nexthop[0] == 0)
860
msg_fatal("empty nexthop hostname");
861
if (rcpt_list->len <= 0)
862
msg_fatal("recipient count: %d", rcpt_list->len);
863
if (attr.command == 0) {
864
get_service_params(&conf, service);
865
get_service_attr(&attr, argv);
869
* The D flag cannot be specified for multi-recipient deliveries.
871
if ((attr.flags & MAIL_COPY_DELIVERED) && (rcpt_list->len > 1)) {
872
deliver_status = eval_command_status(PIPE_STAT_DEFER, service,
873
request, request->fp,
874
"mailer configuration error");
875
msg_warn("pipe flag `D' requires %s_destination_recipient_limit = 1",
877
DELIVER_MSG_CLEANUP();
878
return (deliver_status);
882
* The O flag cannot be specified for multi-recipient deliveries.
884
if ((attr.flags & MAIL_COPY_ORIG_RCPT) && (rcpt_list->len > 1)) {
885
deliver_status = eval_command_status(PIPE_STAT_DEFER, service,
886
request, request->fp,
887
"mailer configuration error");
888
msg_warn("pipe flag `O' requires %s_destination_recipient_limit = 1",
890
DELIVER_MSG_CLEANUP();
891
return (deliver_status);
895
* Check that this agent accepts messages this large.
897
if (attr.size_limit != 0 && request->data_size > attr.size_limit) {
899
msg_info("%s: too big: size_limit = %ld, request->data_size = %ld",
900
myname, (long) attr.size_limit, request->data_size);
902
deliver_status = eval_command_status(PIPE_STAT_BOUNCE, service,
903
request, request->fp, "message too large");
904
DELIVER_MSG_CLEANUP();
905
return (deliver_status);
909
* Don't deliver a trace-only request.
911
if (DEL_REQ_TRACE_ONLY(request->flags)) {
917
for (n = 0; n < request->rcpt_list.len; n++) {
918
rcpt = request->rcpt_list.info + n;
919
status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
920
request->queue_id, rcpt->orig_addr,
921
rcpt->address, rcpt->offset, service,
922
request->arrival_time,
923
"delivers to command: %s", attr.command[0]);
924
if (status == 0 && (request->flags & DEL_REQ_FLAG_SUCCESS))
925
deliver_completed(request->fp, rcpt->offset);
926
deliver_status |= status;
928
DELIVER_MSG_CLEANUP();
929
return (deliver_status);
933
* Deliver. Set the nexthop and sender variables, and expand the command
934
* argument vector. Recipients will be expanded on the fly. XXX Rewrite
935
* envelope and header addresses according to transport-specific
938
if (vstream_fseek(request->fp, request->data_offset, SEEK_SET) < 0)
939
msg_fatal("seek queue file %s: %m", VSTREAM_PATH(request->fp));
941
buf = vstring_alloc(10);
942
if (attr.flags & PIPE_OPT_QUOTE_LOCAL) {
943
quote_822_local(buf, request->sender);
944
dict_update(PIPE_DICT_TABLE, PIPE_DICT_SENDER, STR(buf));
946
dict_update(PIPE_DICT_TABLE, PIPE_DICT_SENDER, request->sender);
947
if (attr.flags & PIPE_OPT_FOLD_HOST) {
948
vstring_strcpy(buf, request->nexthop);
950
dict_update(PIPE_DICT_TABLE, PIPE_DICT_NEXTHOP, STR(buf));
952
dict_update(PIPE_DICT_TABLE, PIPE_DICT_NEXTHOP, request->nexthop);
953
vstring_sprintf(buf, "%ld", (long) request->data_size);
954
dict_update(PIPE_DICT_TABLE, PIPE_DICT_SIZE, STR(buf));
957
if ((expanded_argv = expand_argv(service, attr.command,
958
rcpt_list, attr.flags)) == 0) {
959
deliver_status = eval_command_status(PIPE_STAT_DEFER, service,
960
request, request->fp,
961
"mailer configuration error");
962
DELIVER_MSG_CLEANUP();
963
return (deliver_status);
965
export_env = argv_split(var_export_environ, ", \t\r\n");
967
command_status = pipe_command(request->fp, why,
968
PIPE_CMD_UID, attr.uid,
969
PIPE_CMD_GID, attr.gid,
970
PIPE_CMD_SENDER, request->sender,
971
PIPE_CMD_COPY_FLAGS, attr.flags,
972
PIPE_CMD_ARGV, expanded_argv->argv,
973
PIPE_CMD_TIME_LIMIT, conf.time_limit,
974
PIPE_CMD_EOL, STR(attr.eol),
975
PIPE_CMD_EXPORT, export_env->argv,
976
PIPE_CMD_ORIG_RCPT, rcpt_list->info[0].orig_addr,
977
PIPE_CMD_DELIVERED, rcpt_list->info[0].address,
979
argv_free(export_env);
981
deliver_status = eval_command_status(command_status, service, request,
982
request->fp, vstring_str(why));
987
DELIVER_MSG_CLEANUP();
989
return (deliver_status);
992
/* pipe_service - perform service for client */
994
static void pipe_service(VSTREAM *client_stream, char *service, char **argv)
996
DELIVER_REQUEST *request;
1000
* This routine runs whenever a client connects to the UNIX-domain socket
1001
* dedicated to delivery via external command. What we see below is a
1002
* little protocol to (1) tell the queue manager that we are ready, (2)
1003
* read a request from the queue manager, and (3) report the completion
1004
* status of that request. All connection-management stuff is handled by
1005
* the common code in single_server.c.
1007
if ((request = deliver_request_read(client_stream)) != 0) {
1008
status = deliver_message(request, service, argv);
1009
deliver_request_done(client_stream, request, status);
1013
/* pre_accept - see if tables have changed */
1015
static void pre_accept(char *unused_name, char **unused_argv)
1019
if ((table = dict_changed_name()) != 0) {
1020
msg_info("table %s has changed -- restarting", table);
1025
/* drop_privileges - drop privileges most of the time */
1027
static void drop_privileges(char *unused_name, char **unused_argv)
1029
set_eugid(var_owner_uid, var_owner_gid);
1032
/* pre_init - initialize */
1034
static void pre_init(char *unused_name, char **unused_argv)
1039
/* main - pass control to the single-threaded skeleton */
1041
int main(int argc, char **argv)
1043
static CONFIG_TIME_TABLE time_table[] = {
1044
VAR_COMMAND_MAXTIME, DEF_COMMAND_MAXTIME, &var_command_maxtime, 1, 0,
1048
single_server_main(argc, argv, pipe_service,
1049
MAIL_SERVER_TIME_TABLE, time_table,
1050
MAIL_SERVER_PRE_INIT, pre_init,
1051
MAIL_SERVER_POST_INIT, drop_privileges,
1052
MAIL_SERVER_PRE_ACCEPT, pre_accept,