Postfix3.3.1
pipe.c
[詳解]
1 /*++
2 /* NAME
3 /* pipe 8
4 /* SUMMARY
5 /* Postfix delivery to external command
6 /* SYNOPSIS
7 /* \fBpipe\fR [generic Postfix daemon options] command_attributes...
8 /* DESCRIPTION
9 /* The \fBpipe\fR(8) 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
12 /* manager.
13 /*
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.
17 /*
18 /* The \fBpipe\fR(8) 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
22 /* appropriate.
23 /* SINGLE-RECIPIENT DELIVERY
24 /* .ad
25 /* .fi
26 /* Some destinations cannot handle more than one recipient per
27 /* delivery request. Examples are pagers or fax machines.
28 /* In addition, multi-recipient delivery is undesirable when
29 /* prepending a \fBDelivered-to:\fR or \fBX-Original-To:\fR
30 /* message header.
31 /*
32 /* To prevent Postfix from sending multiple recipients per delivery
33 /* request, specify
34 /* .sp
35 /* .nf
36 /* \fItransport\fB_destination_recipient_limit = 1\fR
37 /* .fi
38 /*
39 /* in the Postfix \fBmain.cf\fR file, where \fItransport\fR
40 /* is the name in the first column of the Postfix \fBmaster.cf\fR
41 /* entry for the pipe-based delivery transport.
42 /* COMMAND ATTRIBUTE SYNTAX
43 /* .ad
44 /* .fi
45 /* The external command attributes are given in the \fBmaster.cf\fR
46 /* file at the end of a service definition. The syntax is as follows:
47 /* .IP "\fBchroot=\fIpathname\fR (optional)"
48 /* Change the process root directory and working directory to
49 /* the named directory. This happens before switching to the
50 /* privileges specified with the \fBuser\fR attribute, and
51 /* before executing the optional \fBdirectory=\fIpathname\fR
52 /* directive. Delivery is deferred in case of failure.
53 /* .sp
54 /* This feature is available as of Postfix 2.3.
55 /* .IP "\fBdirectory=\fIpathname\fR (optional)"
56 /* Change to the named directory before executing the external command.
57 /* The directory must be accessible for the user specified with the
58 /* \fBuser\fR attribute (see below).
59 /* The default working directory is \fB$queue_directory\fR.
60 /* Delivery is deferred in case of failure.
61 /* .sp
62 /* This feature is available as of Postfix 2.2.
63 /* .IP "\fBeol=\fIstring\fR (optional, default: \fB\en\fR)"
64 /* The output record delimiter. Typically one would use either
65 /* \fB\er\en\fR or \fB\en\fR. The usual C-style backslash escape
66 /* sequences are recognized: \fB\ea \eb \ef \en \er \et \ev
67 /* \e\fIddd\fR (up to three octal digits) and \fB\e\e\fR.
68 /* .IP "\fBflags=BDFORXhqu.>\fR (optional)"
69 /* Optional message processing flags. By default, a message is
70 /* copied unchanged.
71 /* .RS
72 /* .IP \fBB\fR
73 /* Append a blank line at the end of each message. This is required
74 /* by some mail user agents that recognize "\fBFrom \fR" lines only
75 /* when preceded by a blank line.
76 /* .IP \fBD\fR
77 /* Prepend a "\fBDelivered-To: \fIrecipient\fR" message header with the
78 /* envelope recipient address. Note: for this to work, the
79 /* \fItransport\fB_destination_recipient_limit\fR must be 1
80 /* (see SINGLE-RECIPIENT DELIVERY above for details).
81 /* .sp
82 /* The \fBD\fR flag also enforces loop detection (Postfix 2.5 and later):
83 /* if a message already contains a \fBDelivered-To:\fR header
84 /* with the same recipient address, then the message is
85 /* returned as undeliverable. The address comparison is case
86 /* insensitive.
87 /* .sp
88 /* This feature is available as of Postfix 2.0.
89 /* .IP \fBF\fR
90 /* Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
91 /* the message content.
92 /* This is expected by, for example, \fBUUCP\fR software.
93 /* .IP \fBO\fR
94 /* Prepend an "\fBX-Original-To: \fIrecipient\fR" message header
95 /* with the recipient address as given to Postfix. Note: for this to
96 /* work, the \fItransport\fB_destination_recipient_limit\fR must be 1
97 /* (see SINGLE-RECIPIENT DELIVERY above for details).
98 /* .sp
99 /* This feature is available as of Postfix 2.0.
100 /* .IP \fBR\fR
101 /* Prepend a \fBReturn-Path:\fR message header with the envelope sender
102 /* address.
103 /* .IP \fBX\fR
104 /* Indicate that the external command performs final delivery.
105 /* This flag affects the status reported in "success" DSN
106 /* (delivery status notification) messages, and changes it
107 /* from "relayed" into "delivered".
108 /* .sp
109 /* This feature is available as of Postfix 2.5.
110 /* .IP \fBh\fR
111 /* Fold the command-line \fB$original_recipient\fR and
112 /* \fB$recipient\fR address domain part
113 /* (text to the right of the right-most \fB@\fR character) to
114 /* lower case; fold the entire command-line \fB$domain\fR and
115 /* \fB$nexthop\fR host or domain information to lower case.
116 /* This is recommended for delivery via \fBUUCP\fR.
117 /* .IP \fBq\fR
118 /* Quote white space and other special characters in the command-line
119 /* \fB$sender\fR, \fB$original_recipient\fR and \fB$recipient\fR
120 /* address localparts (text to the
121 /* left of the right-most \fB@\fR character), according to an 8-bit
122 /* transparent version of RFC 822.
123 /* This is recommended for delivery via \fBUUCP\fR or \fBBSMTP\fR.
124 /* .sp
125 /* The result is compatible with the address parsing of command-line
126 /* recipients by the Postfix \fBsendmail\fR(1) mail submission command.
127 /* .sp
128 /* The \fBq\fR flag affects only entire addresses, not the partial
129 /* address information from the \fB$user\fR, \fB$extension\fR or
130 /* \fB$mailbox\fR command-line macros.
131 /* .IP \fBu\fR
132 /* Fold the command-line \fB$original_recipient\fR and
133 /* \fB$recipient\fR address localpart (text to
134 /* the left of the right-most \fB@\fR character) to lower case.
135 /* This is recommended for delivery via \fBUUCP\fR.
136 /* .IP \fB.\fR
137 /* Prepend "\fB.\fR" to lines starting with "\fB.\fR". This is needed
138 /* by, for example, \fBBSMTP\fR software.
139 /* .IP \fB>\fR
140 /* Prepend "\fB>\fR" to lines starting with "\fBFrom \fR". This is expected
141 /* by, for example, \fBUUCP\fR software.
142 /* .RE
143 /* .IP "\fBnull_sender\fR=\fIreplacement\fR (default: MAILER-DAEMON)"
144 /* Replace the null sender address (typically used for delivery
145 /* status notifications) with the specified text
146 /* when expanding the \fB$sender\fR command-line macro, and
147 /* when generating a From_ or Return-Path: message header.
148 /*
149 /* If the null sender replacement text is a non-empty string
150 /* then it is affected by the \fBq\fR flag for address quoting
151 /* in command-line arguments.
152 /*
153 /* The null sender replacement text may be empty; this form
154 /* is recommended for content filters that feed mail back into
155 /* Postfix. The empty sender address is not affected by the
156 /* \fBq\fR flag for address quoting in command-line arguments.
157 /* .sp
158 /* Caution: a null sender address is easily mis-parsed by
159 /* naive software. For example, when the \fBpipe\fR(8) daemon
160 /* executes a command such as:
161 /* .sp
162 /* .nf
163 /* \fIWrong\fR: command -f$sender -- $recipient
164 /* .fi
165 /* .IP
166 /* the command will mis-parse the -f option value when the
167 /* sender address is a null string. For correct parsing,
168 /* specify \fB$sender\fR as an argument by itself:
169 /* .sp
170 /* .nf
171 /* \fIRight\fR: command -f $sender -- $recipient
172 /* .fi
173 /* .IP
174 /* This feature is available as of Postfix 2.3.
175 /* .IP "\fBsize\fR=\fIsize_limit\fR (optional)"
176 /* Don't deliver messages that exceed this size limit (in
177 /* bytes); return them to the sender instead.
178 /* .IP "\fBuser\fR=\fIusername\fR (required)"
179 /* .IP "\fBuser\fR=\fIusername\fR:\fIgroupname\fR"
180 /* Execute the external command with the user ID and group ID of the
181 /* specified \fIusername\fR. The software refuses to execute
182 /* commands with root privileges, or with the privileges of the
183 /* mail system owner. If \fIgroupname\fR is specified, the
184 /* corresponding group ID is used instead of the group ID of
185 /* \fIusername\fR.
186 /* .IP "\fBargv\fR=\fIcommand\fR... (required)"
187 /* The command to be executed. This must be specified as the
188 /* last command attribute.
189 /* The command is executed directly, i.e. without interpretation of
190 /* shell meta characters by a shell command interpreter.
191 /* .sp
192 /* Specify "{" and "}" around command arguments that contain
193 /* whitespace (Postfix 3.0 and later). Whitespace
194 /* after "{" and before "}" is ignored.
195 /* .sp
196 /* In the command argument vector, the following macros are recognized
197 /* and replaced with corresponding information from the Postfix queue
198 /* manager delivery request.
199 /* .sp
200 /* In addition to the form ${\fIname\fR}, the forms $\fIname\fR and
201 /* the deprecated form $(\fIname\fR) are also recognized.
202 /* Specify \fB$$\fR where a single \fB$\fR is wanted.
203 /* .RS
204 /* .IP \fB${client_address}\fR
205 /* This macro expands to the remote client network address.
206 /* .sp
207 /* This feature is available as of Postfix 2.2.
208 /* .IP \fB${client_helo}\fR
209 /* This macro expands to the remote client HELO command parameter.
210 /* .sp
211 /* This feature is available as of Postfix 2.2.
212 /* .IP \fB${client_hostname}\fR
213 /* This macro expands to the remote client hostname.
214 /* .sp
215 /* This feature is available as of Postfix 2.2.
216 /* .IP \fB${client_port}\fR
217 /* This macro expands to the remote client TCP port number.
218 /* .sp
219 /* This feature is available as of Postfix 2.5.
220 /* .IP \fB${client_protocol}\fR
221 /* This macro expands to the remote client protocol.
222 /* .sp
223 /* This feature is available as of Postfix 2.2.
224 /* .IP \fB${domain}\fR
225 /* This macro expands to the domain portion of the recipient
226 /* address. For example, with an address \fIuser+foo@domain\fR
227 /* the domain is \fIdomain\fR.
228 /* .sp
229 /* This information is modified by the \fBh\fR flag for case folding.
230 /* .sp
231 /* This feature is available as of Postfix 2.5.
232 /* .IP \fB${extension}\fR
233 /* This macro expands to the extension part of a recipient address.
234 /* For example, with an address \fIuser+foo@domain\fR the extension is
235 /* \fIfoo\fR.
236 /* .sp
237 /* A command-line argument that contains \fB${extension}\fR expands
238 /* into as many command-line arguments as there are recipients.
239 /* .sp
240 /* This information is modified by the \fBu\fR flag for case folding.
241 /* .IP \fB${mailbox}\fR
242 /* This macro expands to the complete local part of a recipient address.
243 /* For example, with an address \fIuser+foo@domain\fR the mailbox is
244 /* \fIuser+foo\fR.
245 /* .sp
246 /* A command-line argument that contains \fB${mailbox}\fR
247 /* expands to as many command-line arguments as there are recipients.
248 /* .sp
249 /* This information is modified by the \fBu\fR flag for case folding.
250 /* .IP \fB${nexthop}\fR
251 /* This macro expands to the next-hop hostname.
252 /* .sp
253 /* This information is modified by the \fBh\fR flag for case folding.
254 /* .IP \fB${original_recipient}\fR
255 /* This macro expands to the complete recipient address before any
256 /* address rewriting or aliasing.
257 /* .sp
258 /* A command-line argument that contains
259 /* \fB${original_recipient}\fR expands to as many
260 /* command-line arguments as there are recipients.
261 /* .sp
262 /* This information is modified by the \fBhqu\fR flags for quoting
263 /* and case folding.
264 /* .sp
265 /* This feature is available as of Postfix 2.5.
266 /* .IP \fB${queue_id}\fR
267 /* This macro expands to the queue id.
268 /* .sp
269 /* This feature is available as of Postfix 2.11.
270 /* .IP \fB${recipient}\fR
271 /* This macro expands to the complete recipient address.
272 /* .sp
273 /* A command-line argument that contains \fB${recipient}\fR
274 /* expands to as many command-line arguments as there are recipients.
275 /* .sp
276 /* This information is modified by the \fBhqu\fR flags for quoting
277 /* and case folding.
278 /* .IP \fB${sasl_method}\fR
279 /* This macro expands to the name of the SASL authentication
280 /* mechanism in the AUTH command when the Postfix SMTP server
281 /* received the message.
282 /* .sp
283 /* This feature is available as of Postfix 2.2.
284 /* .IP \fB${sasl_sender}\fR
285 /* This macro expands to the SASL sender name (i.e. the original
286 /* submitter as per RFC 4954) in the MAIL FROM command when
287 /* the Postfix SMTP server received the message.
288 /* .sp
289 /* This feature is available as of Postfix 2.2.
290 /* .IP \fB${sasl_username}\fR
291 /* This macro expands to the SASL user name in the AUTH command
292 /* when the Postfix SMTP server received the message.
293 /* .sp
294 /* This feature is available as of Postfix 2.2.
295 /* .IP \fB${sender}\fR
296 /* This macro expands to the envelope sender address. By default,
297 /* the null sender address expands to MAILER-DAEMON; this can
298 /* be changed with the \fBnull_sender\fR attribute, as described
299 /* above.
300 /* .sp
301 /* This information is modified by the \fBq\fR flag for quoting.
302 /* .IP \fB${size}\fR
303 /* This macro expands to Postfix's idea of the message size, which
304 /* is an approximation of the size of the message as delivered.
305 /* .IP \fB${user}\fR
306 /* This macro expands to the username part of a recipient address.
307 /* For example, with an address \fIuser+foo@domain\fR the username
308 /* part is \fIuser\fR.
309 /* .sp
310 /* A command-line argument that contains \fB${user}\fR expands
311 /* into as many command-line arguments as there are recipients.
312 /* .sp
313 /* This information is modified by the \fBu\fR flag for case folding.
314 /* .RE
315 /* STANDARDS
316 /* RFC 3463 (Enhanced status codes)
317 /* DIAGNOSTICS
318 /* Command exit status codes are expected to
319 /* follow the conventions defined in <\fBsysexits.h\fR>.
320 /* Exit status 0 means normal successful completion.
321 /*
322 /* In the case of a non-zero exit status, a limited amount of
323 /* command output is logged, and reported in a delivery status
324 /* notification. When the output begins with a 4.X.X or 5.X.X
325 /* enhanced status code, the status code takes precedence over
326 /* the non-zero exit status (Postfix version 2.3 and later).
327 /*
328 /* After successful delivery (zero exit status) a limited
329 /* amount of command output is logged, and reported in "success"
330 /* delivery status notifications (Postfix 3.0 and later).
331 /* This command output is not examined for the presence of an
332 /* enhanced status code.
333 /*
334 /* Problems and transactions are logged to \fBsyslogd\fR(8).
335 /* Corrupted message files are marked so that the queue manager
336 /* can move them to the \fBcorrupt\fR queue for further inspection.
337 /* SECURITY
338 /* .fi
339 /* .ad
340 /* This program needs a dual personality 1) to access the private
341 /* Postfix queue and IPC mechanisms, and 2) to execute external
342 /* commands as the specified user. It is therefore security sensitive.
343 /* CONFIGURATION PARAMETERS
344 /* .ad
345 /* .fi
346 /* Changes to \fBmain.cf\fR are picked up automatically as \fBpipe\fR(8)
347 /* processes run for only a limited amount of time. Use the command
348 /* "\fBpostfix reload\fR" to speed up a change.
349 /*
350 /* The text below provides only a parameter summary. See
351 /* \fBpostconf\fR(5) for more details including examples.
352 /* RESOURCE AND RATE CONTROLS
353 /* .ad
354 /* .fi
355 /* In the text below, \fItransport\fR is the first field in a
356 /* \fBmaster.cf\fR entry.
357 /* .IP "\fBtransport_time_limit ($command_time_limit)\fR"
358 /* A transport-specific override for the command_time_limit parameter
359 /* value, where \fItransport\fR is the master.cf name of the message
360 /* delivery transport.
361 /* .PP
362 /* Implemented in the qmgr(8) daemon:
363 /* .IP "\fBtransport_destination_concurrency_limit ($default_destination_concurrency_limit)\fR"
364 /* A transport-specific override for the
365 /* default_destination_concurrency_limit parameter value, where
366 /* \fItransport\fR is the master.cf name of the message delivery
367 /* transport.
368 /* .IP "\fBtransport_destination_recipient_limit ($default_destination_recipient_limit)\fR"
369 /* A transport-specific override for the
370 /* default_destination_recipient_limit parameter value, where
371 /* \fItransport\fR is the master.cf name of the message delivery
372 /* transport.
373 /* MISCELLANEOUS CONTROLS
374 /* .ad
375 /* .fi
376 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
377 /* The default location of the Postfix main.cf and master.cf
378 /* configuration files.
379 /* .IP "\fBdaemon_timeout (18000s)\fR"
380 /* How much time a Postfix daemon process may take to handle a
381 /* request before it is terminated by a built-in watchdog timer.
382 /* .IP "\fBdelay_logging_resolution_limit (2)\fR"
383 /* The maximal number of digits after the decimal point when logging
384 /* sub-second delay values.
385 /* .IP "\fBexport_environment (see 'postconf -d' output)\fR"
386 /* The list of environment variables that a Postfix process will export
387 /* to non-Postfix processes.
388 /* .IP "\fBipc_timeout (3600s)\fR"
389 /* The time limit for sending or receiving information over an internal
390 /* communication channel.
391 /* .IP "\fBmail_owner (postfix)\fR"
392 /* The UNIX system account that owns the Postfix queue and most Postfix
393 /* daemon processes.
394 /* .IP "\fBmax_idle (100s)\fR"
395 /* The maximum amount of time that an idle Postfix daemon process waits
396 /* for an incoming connection before terminating voluntarily.
397 /* .IP "\fBmax_use (100)\fR"
398 /* The maximal number of incoming connections that a Postfix daemon
399 /* process will service before terminating voluntarily.
400 /* .IP "\fBprocess_id (read-only)\fR"
401 /* The process ID of a Postfix command or daemon process.
402 /* .IP "\fBprocess_name (read-only)\fR"
403 /* The process name of a Postfix command or daemon process.
404 /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
405 /* The location of the Postfix top-level queue directory.
406 /* .IP "\fBrecipient_delimiter (empty)\fR"
407 /* The set of characters that can separate a user name from its
408 /* extension (example: user+foo), or a .forward file name from its
409 /* extension (example: .forward+foo).
410 /* .IP "\fBsyslog_facility (mail)\fR"
411 /* The syslog facility of Postfix logging.
412 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
413 /* A prefix that is prepended to the process name in syslog
414 /* records, so that, for example, "smtpd" becomes "prefix/smtpd".
415 /* .PP
416 /* Available in Postfix version 3.0 and later:
417 /* .IP "\fBpipe_delivery_status_filter ($default_delivery_status_filter)\fR"
418 /* Optional filter for the \fBpipe\fR(8) delivery agent to change the
419 /* delivery status code or explanatory text of successful or unsuccessful
420 /* deliveries.
421 /* .PP
422 /* Available in Postfix version 3.3 and later:
423 /* .IP "\fBenable_original_recipient (yes)\fR"
424 /* Enable support for the original recipient address after an
425 /* address is rewritten to a different address (for example with
426 /* aliasing or with canonical mapping).
427 /* .IP "\fBservice_name (read-only)\fR"
428 /* The master.cf service name of a Postfix daemon process.
429 /* SEE ALSO
430 /* qmgr(8), queue manager
431 /* bounce(8), delivery status reports
432 /* postconf(5), configuration parameters
433 /* master(5), generic daemon options
434 /* master(8), process manager
435 /* syslogd(8), system logging
436 /* LICENSE
437 /* .ad
438 /* .fi
439 /* The Secure Mailer license must be distributed with this software.
440 /* AUTHOR(S)
441 /* Wietse Venema
442 /* IBM T.J. Watson Research
443 /* P.O. Box 704
444 /* Yorktown Heights, NY 10598, USA
445 /*
446 /* Wietse Venema
447 /* Google, Inc.
448 /* 111 8th Avenue
449 /* New York, NY 10011, USA
450 /*--*/
451 
452 /* System library. */
453 
454 #include <sys_defs.h>
455 #include <unistd.h>
456 #include <stdlib.h>
457 #include <string.h>
458 #include <pwd.h>
459 #include <grp.h>
460 #include <fcntl.h>
461 #include <ctype.h>
462 
463 #ifdef STRCASECMP_IN_STRINGS_H
464 #include <strings.h>
465 #endif
466 
467 /* Utility library. */
468 
469 #include <msg.h>
470 #include <vstream.h>
471 #include <vstring.h>
472 #include <argv.h>
473 #include <htable.h>
474 #include <dict.h>
475 #include <iostuff.h>
476 #include <mymalloc.h>
477 #include <mac_parse.h>
478 #include <set_eugid.h>
479 #include <split_at.h>
480 #include <stringops.h>
481 
482 /* Global library. */
483 
484 #include <recipient_list.h>
485 #include <deliver_request.h>
486 #include <mail_params.h>
487 #include <mail_version.h>
488 #include <mail_conf.h>
489 #include <bounce.h>
490 #include <defer.h>
491 #include <deliver_completed.h>
492 #include <sent.h>
493 #include <pipe_command.h>
494 #include <mail_copy.h>
495 #include <mail_addr.h>
496 #include <canon_addr.h>
497 #include <split_addr.h>
498 #include <off_cvt.h>
499 #include <quote_822_local.h>
500 #include <flush_clnt.h>
501 #include <dsn_util.h>
502 #include <dsn_buf.h>
503 #include <sys_exits.h>
504 #include <delivered_hdr.h>
505 #include <fold_addr.h>
506 #include <mail_parm_split.h>
507 
508 /* Single server skeleton. */
509 
510 #include <mail_server.h>
511 
512 /* Application-specific. */
513 
514  /*
515  * The mini symbol table name and keys used for expanding macros in
516  * command-line arguments.
517  *
518  * XXX Update the parse_callback() routine when something gets added here,
519  * even when the macro is not recipient dependent.
520  */
521 #define PIPE_DICT_TABLE "pipe_command" /* table name */
522 #define PIPE_DICT_NEXTHOP "nexthop" /* key */
523 #define PIPE_DICT_RCPT "recipient" /* key */
524 #define PIPE_DICT_ORIG_RCPT "original_recipient" /* key */
525 #define PIPE_DICT_SENDER "sender"/* key */
526 #define PIPE_DICT_USER "user" /* key */
527 #define PIPE_DICT_EXTENSION "extension" /* key */
528 #define PIPE_DICT_MAILBOX "mailbox" /* key */
529 #define PIPE_DICT_DOMAIN "domain"/* key */
530 #define PIPE_DICT_SIZE "size" /* key */
531 #define PIPE_DICT_CLIENT_ADDR "client_address" /* key */
532 #define PIPE_DICT_CLIENT_NAME "client_hostname" /* key */
533 #define PIPE_DICT_CLIENT_PORT "client_port" /* key */
534 #define PIPE_DICT_CLIENT_PROTO "client_protocol" /* key */
535 #define PIPE_DICT_CLIENT_HELO "client_helo" /* key */
536 #define PIPE_DICT_SASL_METHOD "sasl_method" /* key */
537 #define PIPE_DICT_SASL_USERNAME "sasl_username" /* key */
538 #define PIPE_DICT_SASL_SENDER "sasl_sender" /* key */
539 #define PIPE_DICT_QUEUE_ID "queue_id" /* key */
540 
541  /*
542  * Flags used to pass back the type of special parameter found by
543  * parse_callback.
544  */
545 #define PIPE_FLAG_RCPT (1<<0)
546 #define PIPE_FLAG_USER (1<<1)
547 #define PIPE_FLAG_EXTENSION (1<<2)
548 #define PIPE_FLAG_MAILBOX (1<<3)
549 #define PIPE_FLAG_DOMAIN (1<<4)
550 #define PIPE_FLAG_ORIG_RCPT (1<<5)
551 
552  /*
553  * Additional flags. These are colocated with mail_copy() flags. Allow some
554  * space for extension of the mail_copy() interface.
555  */
556 #define PIPE_OPT_FOLD_BASE (16)
557 #define PIPE_OPT_FOLD_USER (FOLD_ADDR_USER << PIPE_OPT_FOLD_BASE)
558 #define PIPE_OPT_FOLD_HOST (FOLD_ADDR_HOST << PIPE_OPT_FOLD_BASE)
559 #define PIPE_OPT_QUOTE_LOCAL (1 << (PIPE_OPT_FOLD_BASE + 2))
560 #define PIPE_OPT_FINAL_DELIVERY (1 << (PIPE_OPT_FOLD_BASE + 3))
561 
562 #define PIPE_OPT_FOLD_ALL (FOLD_ADDR_ALL << PIPE_OPT_FOLD_BASE)
563 #define PIPE_OPT_FOLD_FLAGS(f) \
564  (((f) & PIPE_OPT_FOLD_ALL) >> PIPE_OPT_FOLD_BASE)
565 
566  /*
567  * Tunable parameters. Values are taken from the config file, after
568  * prepending the service name to _name, and so on.
569  */
570 int var_command_maxtime; /* You can now leave this here. */
571 
572  /*
573  * Other main.cf parameters.
574  */
576 
577  /*
578  * For convenience. Instead of passing around lists of parameters, bundle
579  * them up in convenient structures.
580  */
581 
582  /*
583  * Structure for service-specific configuration parameters.
584  */
585 typedef struct {
586  int time_limit; /* per-service time limit */
587 } PIPE_PARAMS;
588 
589  /*
590  * Structure for command-line parameters.
591  */
592 typedef struct {
593  char **command; /* argument vector */
594  uid_t uid; /* command privileges */
595  gid_t gid; /* command privileges */
596  int flags; /* mail_copy() flags */
597  char *exec_dir; /* working directory */
598  char *chroot_dir; /* chroot directory */
599  VSTRING *eol; /* output record delimiter */
600  VSTRING *null_sender; /* null sender expansion */
601  off_t size_limit; /* max size in bytes we will accept */
602 } PIPE_ATTR;
603 
604  /*
605  * Structure for command-line parameter macro expansion.
606  */
607 typedef struct {
608  const char *service; /* for warnings */
609  int expand_flag; /* callback result */
610 } PIPE_STATE;
611 
612  /*
613  * Silly little macros.
614  */
615 #define STR vstring_str
616 
617 /* parse_callback - callback for mac_parse() */
618 
619 static int parse_callback(int type, VSTRING *buf, void *context)
620 {
621  PIPE_STATE *state = (PIPE_STATE *) context;
622  struct cmd_flags {
623  const char *name;
624  int flags;
625  };
626  static struct cmd_flags cmd_flags[] = {
630  PIPE_DICT_SENDER, 0,
635  PIPE_DICT_SIZE, 0,
645  0, 0,
646  };
647  struct cmd_flags *p;
648 
649  /*
650  * See if this command-line argument references a special macro.
651  */
652  if (type == MAC_PARSE_VARNAME) {
653  for (p = cmd_flags; /* see below */ ; p++) {
654  if (p->name == 0) {
655  msg_warn("file %s/%s: service %s: unknown macro name: \"%s\"",
657  state->service, vstring_str(buf));
658  return (MAC_PARSE_ERROR);
659  } else if (strcmp(vstring_str(buf), p->name) == 0) {
660  state->expand_flag |= p->flags;
661  return (0);
662  }
663  }
664  }
665  return (0);
666 }
667 
668 /* morph_recipient - morph a recipient address */
669 
670 static void morph_recipient(VSTRING *buf, const char *address, int flags)
671 {
672  VSTRING *temp = vstring_alloc(100);
673 
674  /*
675  * Quote the recipient address as appropriate.
676  */
677  if (flags & PIPE_OPT_QUOTE_LOCAL)
678  quote_822_local(temp, address);
679  else
680  vstring_strcpy(temp, address);
681 
682  /*
683  * Fold the recipient address as appropriate.
684  */
685  fold_addr(buf, STR(temp), PIPE_OPT_FOLD_FLAGS(flags));
686 
687  vstring_free(temp);
688 }
689 
690 /* expand_argv - expand macros in the argument vector */
691 
692 static ARGV *expand_argv(const char *service, char **argv,
693  RECIPIENT_LIST *rcpt_list, int flags)
694 {
695  VSTRING *buf = vstring_alloc(100);
696  ARGV *result;
697  char **cpp;
698  PIPE_STATE state;
699  int i;
700  char *ext;
701  char *dom;
702 
703  /*
704  * This appears to be simple operation (replace $name by its expansion).
705  * However, it becomes complex because a command-line argument that
706  * references $recipient must expand to as many command-line arguments as
707  * there are recipients (that's wat programs called by sendmail expect).
708  * So we parse each command-line argument, and depending on what we find,
709  * we either expand the argument just once, or we expand it once for each
710  * recipient. In either case we end up parsing the command-line argument
711  * twice. The amount of CPU time wasted will be negligible.
712  *
713  * Note: we can't use recursive macro expansion here, because recursion
714  * would screw up mail addresses that contain $ characters.
715  */
716 #define NO 0
717 #define EARLY_RETURN(x) { argv_free(result); vstring_free(buf); return (x); }
718 
719  result = argv_alloc(1);
720  for (cpp = argv; *cpp; cpp++) {
721  state.service = service;
722  state.expand_flag = 0;
723  if (mac_parse(*cpp, parse_callback, (void *) &state) & MAC_PARSE_ERROR)
724  EARLY_RETURN(0);
725  if (state.expand_flag == 0) { /* no $recipient etc. */
726  argv_add(result, dict_eval(PIPE_DICT_TABLE, *cpp, NO), ARGV_END);
727  } else { /* contains $recipient etc. */
728  for (i = 0; i < rcpt_list->len; i++) {
729 
730  /*
731  * This argument contains $recipient.
732  */
733  if (state.expand_flag & PIPE_FLAG_RCPT) {
734  morph_recipient(buf, rcpt_list->info[i].address, flags);
736  }
737 
738  /*
739  * This argument contains $original_recipient.
740  */
741  if (state.expand_flag & PIPE_FLAG_ORIG_RCPT) {
742  morph_recipient(buf, rcpt_list->info[i].orig_addr, flags);
744  }
745 
746  /*
747  * This argument contains $user. Extract the plain user name.
748  * Either anything to the left of the extension delimiter or,
749  * in absence of the latter, anything to the left of the
750  * rightmost @.
751  *
752  * Beware: if the user name is blank (e.g. +user@host), the
753  * argument is suppressed. This is necessary to allow for
754  * cyrus bulletin-board (global mailbox) delivery. XXX But,
755  * skipping empty user parts will also prevent other
756  * expansions of this specific command-line argument.
757  */
758  if (state.expand_flag & PIPE_FLAG_USER) {
759  morph_recipient(buf, rcpt_list->info[i].address,
760  flags & PIPE_OPT_FOLD_ALL);
761  if (split_at_right(STR(buf), '@') == 0)
762  msg_warn("no @ in recipient address: %s",
763  rcpt_list->info[i].address);
764  if (*var_rcpt_delim)
766  if (*STR(buf) == 0)
767  continue;
769  }
770 
771  /*
772  * This argument contains $extension. Extract the recipient
773  * extension: anything between the leftmost extension
774  * delimiter and the rightmost @. The extension may be blank.
775  */
776  if (state.expand_flag & PIPE_FLAG_EXTENSION) {
777  morph_recipient(buf, rcpt_list->info[i].address,
778  flags & PIPE_OPT_FOLD_ALL);
779  if (split_at_right(STR(buf), '@') == 0)
780  msg_warn("no @ in recipient address: %s",
781  rcpt_list->info[i].address);
782  if (*var_rcpt_delim == 0
783  || (ext = split_addr(STR(buf), var_rcpt_delim)) == 0)
784  ext = ""; /* insert null arg */
786  }
787 
788  /*
789  * This argument contains $mailbox. Extract the mailbox name:
790  * anything to the left of the rightmost @.
791  */
792  if (state.expand_flag & PIPE_FLAG_MAILBOX) {
793  morph_recipient(buf, rcpt_list->info[i].address,
794  flags & PIPE_OPT_FOLD_ALL);
795  if (split_at_right(STR(buf), '@') == 0)
796  msg_warn("no @ in recipient address: %s",
797  rcpt_list->info[i].address);
799  }
800 
801  /*
802  * This argument contains $domain. Extract the domain name:
803  * anything to the right of the rightmost @.
804  */
805  if (state.expand_flag & PIPE_FLAG_DOMAIN) {
806  morph_recipient(buf, rcpt_list->info[i].address,
807  flags & PIPE_OPT_FOLD_ALL);
808  dom = split_at_right(STR(buf), '@');
809  if (dom == 0) {
810  msg_warn("no @ in recipient address: %s",
811  rcpt_list->info[i].address);
812  dom = ""; /* insert null arg */
813  }
815  }
816 
817  /*
818  * Done.
819  */
820  argv_add(result, dict_eval(PIPE_DICT_TABLE, *cpp, NO), ARGV_END);
821  }
822  }
823  }
824  argv_terminate(result);
825  vstring_free(buf);
826  return (result);
827 }
828 
829 /* get_service_params - get service-name dependent config information */
830 
831 static void get_service_params(PIPE_PARAMS *config, char *service)
832 {
833  const char *myname = "get_service_params";
834 
835  /*
836  * Figure out the command time limit for this transport.
837  */
838  config->time_limit =
839  get_mail_conf_time2(service, _MAXTIME, var_command_maxtime, 's', 1, 0);
840 
841  /*
842  * Give the poor tester a clue of what is going on.
843  */
844  if (msg_verbose)
845  msg_info("%s: time_limit %d", myname, config->time_limit);
846 }
847 
848 /* get_service_attr - get command-line attributes */
849 
850 static void get_service_attr(PIPE_ATTR *attr, char **argv)
851 {
852  const char *myname = "get_service_attr";
853  struct passwd *pwd;
854  struct group *grp;
855  char *user; /* user name */
856  char *group; /* group name */
857  char *size; /* max message size */
858  char *cp;
859 
860  /*
861  * Initialize.
862  */
863  user = 0;
864  group = 0;
865  attr->command = 0;
866  attr->flags = 0;
867  attr->exec_dir = 0;
868  attr->chroot_dir = 0;
869  attr->eol = vstring_strcpy(vstring_alloc(1), "\n");
871  attr->size_limit = 0;
872 
873  /*
874  * Iterate over the command-line attribute list.
875  */
876  for ( /* void */ ; *argv != 0; argv++) {
877 
878  /*
879  * flags=stuff
880  */
881  if (strncasecmp("flags=", *argv, sizeof("flags=") - 1) == 0) {
882  for (cp = *argv + sizeof("flags=") - 1; *cp; cp++) {
883  switch (*cp) {
884  case 'B':
885  attr->flags |= MAIL_COPY_BLANK;
886  break;
887  case 'D':
888  attr->flags |= MAIL_COPY_DELIVERED;
889  break;
890  case 'F':
891  attr->flags |= MAIL_COPY_FROM;
892  break;
893  case 'O':
894  attr->flags |= MAIL_COPY_ORIG_RCPT;
895  break;
896  case 'R':
897  attr->flags |= MAIL_COPY_RETURN_PATH;
898  break;
899  case 'X':
901  break;
902  case '.':
903  attr->flags |= MAIL_COPY_DOT;
904  break;
905  case '>':
906  attr->flags |= MAIL_COPY_QUOTE;
907  break;
908  case 'h':
909  attr->flags |= PIPE_OPT_FOLD_HOST;
910  break;
911  case 'q':
912  attr->flags |= PIPE_OPT_QUOTE_LOCAL;
913  break;
914  case 'u':
915  attr->flags |= PIPE_OPT_FOLD_USER;
916  break;
917  default:
918  msg_fatal("unknown flag: %c (ignored)", *cp);
919  break;
920  }
921  }
922  }
923 
924  /*
925  * user=username[:groupname]
926  */
927  else if (strncasecmp("user=", *argv, sizeof("user=") - 1) == 0) {
928  user = *argv + sizeof("user=") - 1;
929  if ((group = split_at(user, ':')) != 0) /* XXX clobbers argv */
930  if (*group == 0)
931  group = 0;
932  if ((pwd = getpwnam(user)) == 0)
933  msg_fatal("%s: unknown username: %s", myname, user);
934  attr->uid = pwd->pw_uid;
935  if (group != 0) {
936  if ((grp = getgrnam(group)) == 0)
937  msg_fatal("%s: unknown group: %s", myname, group);
938  attr->gid = grp->gr_gid;
939  } else {
940  attr->gid = pwd->pw_gid;
941  }
942  }
943 
944  /*
945  * directory=string
946  */
947  else if (strncasecmp("directory=", *argv, sizeof("directory=") - 1) == 0) {
948  attr->exec_dir = mystrdup(*argv + sizeof("directory=") - 1);
949  }
950 
951  /*
952  * chroot=string
953  */
954  else if (strncasecmp("chroot=", *argv, sizeof("chroot=") - 1) == 0) {
955  attr->chroot_dir = mystrdup(*argv + sizeof("chroot=") - 1);
956  }
957 
958  /*
959  * eol=string
960  */
961  else if (strncasecmp("eol=", *argv, sizeof("eol=") - 1) == 0) {
962  unescape(attr->eol, *argv + sizeof("eol=") - 1);
963  }
964 
965  /*
966  * null_sender=string
967  */
968  else if (strncasecmp("null_sender=", *argv, sizeof("null_sender=") - 1) == 0) {
969  vstring_strcpy(attr->null_sender, *argv + sizeof("null_sender=") - 1);
970  }
971 
972  /*
973  * size=max_message_size (in bytes)
974  */
975  else if (strncasecmp("size=", *argv, sizeof("size=") - 1) == 0) {
976  size = *argv + sizeof("size=") - 1;
977  if ((attr->size_limit = off_cvt_string(size)) < 0)
978  msg_fatal("%s: bad size= value: %s", myname, size);
979  }
980 
981  /*
982  * argv=command...
983  */
984  else if (strncasecmp("argv=", *argv, sizeof("argv=") - 1) == 0) {
985  *argv += sizeof("argv=") - 1; /* XXX clobbers argv */
986  attr->command = argv;
987  break;
988  }
989 
990  /*
991  * Bad.
992  */
993  else
994  msg_fatal("unknown attribute name: %s", *argv);
995  }
996 
997  /*
998  * Sanity checks. Verify that every member has an acceptable value.
999  */
1000  if (user == 0)
1001  msg_fatal("missing user= command-line attribute");
1002  if (attr->command == 0)
1003  msg_fatal("missing argv= command-line attribute");
1004  if (attr->uid == 0)
1005  msg_fatal("user= command-line attribute specifies root privileges");
1006  if (attr->uid == var_owner_uid)
1007  msg_fatal("user= command-line attribute specifies mail system owner %s",
1008  var_mail_owner);
1009  if (attr->gid == 0)
1010  msg_fatal("user= command-line attribute specifies privileged group id 0");
1011  if (attr->gid == var_owner_gid)
1012  msg_fatal("user= command-line attribute specifies mail system owner %s group id %ld",
1013  var_mail_owner, (long) attr->gid);
1014  if (attr->gid == var_sgid_gid)
1015  msg_fatal("user= command-line attribute specifies mail system %s group id %ld",
1016  var_sgid_group, (long) attr->gid);
1017 
1018  /*
1019  * Give the poor tester a clue of what is going on.
1020  */
1021  if (msg_verbose)
1022  msg_info("%s: uid %ld, gid %ld, flags %d, size %ld",
1023  myname, (long) attr->uid, (long) attr->gid,
1024  attr->flags, (long) attr->size_limit);
1025 }
1026 
1027 /* eval_command_status - do something with command completion status */
1028 
1029 static int eval_command_status(int command_status, char *service,
1030  DELIVER_REQUEST *request, PIPE_ATTR *attr,
1031  DSN_BUF *why)
1032 {
1033  RECIPIENT *rcpt;
1034  int status;
1035  int result = 0;
1036  int n;
1037  char *saved_text;
1038 
1039  /*
1040  * Depending on the result, bounce or defer the message, and mark the
1041  * recipient as done where appropriate.
1042  */
1043  switch (command_status) {
1044  case PIPE_STAT_OK:
1045  /* Save the command output before dsb_update() clobbers it. */
1047  VSTRING_LEN(why->reason)) - STR(why->reason));
1048  if (VSTRING_LEN(why->reason) > 0) {
1049  VSTRING_TERMINATE(why->reason);
1050  saved_text =
1053  " (%.100s)", STR(why->reason)));
1054  } else
1055  saved_text = mystrdup(""); /* uses shared R/O storage */
1056  dsb_update(why, "2.0.0", (attr->flags & PIPE_OPT_FINAL_DELIVERY) ?
1057  "delivered" : "relayed", DSB_SKIP_RMTA, DSB_SKIP_REPLY,
1058  "delivered via %s service%s", service, saved_text);
1059  myfree(saved_text);
1060  (void) DSN_FROM_DSN_BUF(why);
1061  for (n = 0; n < request->rcpt_list.len; n++) {
1062  rcpt = request->rcpt_list.info + n;
1063  status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
1064  request->queue_id, &request->msg_stats, rcpt,
1065  service, &why->dsn);
1066  if (status == 0 && (request->flags & DEL_REQ_FLAG_SUCCESS))
1067  deliver_completed(request->fp, rcpt->offset);
1068  result |= status;
1069  }
1070  break;
1071  case PIPE_STAT_BOUNCE:
1072  case PIPE_STAT_DEFER:
1073  (void) DSN_FROM_DSN_BUF(why);
1074  for (n = 0; n < request->rcpt_list.len; n++) {
1075  rcpt = request->rcpt_list.info + n;
1076  /* XXX Maybe encapsulate this with ndr_append(). */
1077  status = (STR(why->status)[0] != '4' ?
1079  (DEL_REQ_TRACE_FLAGS(request->flags),
1080  request->queue_id,
1081  &request->msg_stats, rcpt,
1082  service, &why->dsn);
1083  if (status == 0)
1084  deliver_completed(request->fp, rcpt->offset);
1085  result |= status;
1086  }
1087  break;
1088  case PIPE_STAT_CORRUPT:
1089  /* XXX DSN should we send something? */
1090  result |= DEL_STAT_DEFER;
1091  break;
1092  default:
1093  msg_panic("eval_command_status: bad status %d", command_status);
1094  /* NOTREACHED */
1095  }
1096 
1097  return (result);
1098 }
1099 
1100 /* deliver_message - deliver message with extreme prejudice */
1101 
1102 static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
1103 {
1104  const char *myname = "deliver_message";
1105  static PIPE_PARAMS conf;
1106  static PIPE_ATTR attr;
1107  RECIPIENT_LIST *rcpt_list = &request->rcpt_list;
1108  DSN_BUF *why = dsb_create();
1109  VSTRING *buf;
1110  ARGV *expanded_argv = 0;
1111  int deliver_status;
1112  int command_status;
1113  ARGV *export_env;
1114  const char *sender;
1115 
1116 #define DELIVER_MSG_CLEANUP() { \
1117  dsb_free(why); \
1118  if (expanded_argv) argv_free(expanded_argv); \
1119  }
1120 
1121  if (msg_verbose)
1122  msg_info("%s: from <%s>", myname, request->sender);
1123 
1124  /*
1125  * Sanity checks. The get_service_params() and get_service_attr()
1126  * routines also do some sanity checks. Look up service attributes and
1127  * config information only once. This is safe since the information comes
1128  * from a trusted source, not from the delivery request.
1129  */
1130  if (request->nexthop[0] == 0)
1131  msg_fatal("empty nexthop hostname");
1132  if (rcpt_list->len <= 0)
1133  msg_fatal("recipient count: %d", rcpt_list->len);
1134  if (attr.command == 0) {
1135  get_service_params(&conf, service);
1136  get_service_attr(&attr, argv);
1137  }
1138 
1139  /*
1140  * The D flag cannot be specified for multi-recipient deliveries.
1141  */
1142  if ((attr.flags & MAIL_COPY_DELIVERED) && (rcpt_list->len > 1)) {
1143  dsb_simple(why, "4.3.5", "mail system configuration error");
1144  deliver_status = eval_command_status(PIPE_STAT_DEFER, service,
1145  request, &attr, why);
1146  msg_warn("pipe flag `D' requires %s_destination_recipient_limit = 1",
1147  service);
1149  return (deliver_status);
1150  }
1151 
1152  /*
1153  * The O flag cannot be specified for multi-recipient deliveries.
1154  */
1155  if ((attr.flags & MAIL_COPY_ORIG_RCPT) && (rcpt_list->len > 1)) {
1156  dsb_simple(why, "4.3.5", "mail system configuration error");
1157  deliver_status = eval_command_status(PIPE_STAT_DEFER, service,
1158  request, &attr, why);
1159  msg_warn("pipe flag `O' requires %s_destination_recipient_limit = 1",
1160  service);
1162  return (deliver_status);
1163  }
1164 
1165  /*
1166  * Check that this agent accepts messages this large.
1167  */
1168  if (attr.size_limit != 0 && request->data_size > attr.size_limit) {
1169  if (msg_verbose)
1170  msg_info("%s: too big: size_limit = %ld, request->data_size = %ld",
1171  myname, (long) attr.size_limit, request->data_size);
1172  dsb_simple(why, "5.2.3", "message too large");
1173  deliver_status = eval_command_status(PIPE_STAT_BOUNCE, service,
1174  request, &attr, why);
1176  return (deliver_status);
1177  }
1178 
1179  /*
1180  * Don't deliver a trace-only request.
1181  */
1182  if (DEL_REQ_TRACE_ONLY(request->flags)) {
1183  RECIPIENT *rcpt;
1184  int status;
1185  int n;
1186 
1187  deliver_status = 0;
1188  dsb_simple(why, "2.0.0", "delivers to command: %s", attr.command[0]);
1189  (void) DSN_FROM_DSN_BUF(why);
1190  for (n = 0; n < request->rcpt_list.len; n++) {
1191  rcpt = request->rcpt_list.info + n;
1192  status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
1193  request->queue_id, &request->msg_stats,
1194  rcpt, service, &why->dsn);
1195  if (status == 0 && (request->flags & DEL_REQ_FLAG_SUCCESS))
1196  deliver_completed(request->fp, rcpt->offset);
1197  deliver_status |= status;
1198  }
1200  return (deliver_status);
1201  }
1202 
1203  /*
1204  * Report mail delivery loops. By definition, this requires
1205  * single-recipient delivery. Don't silently lose recipients.
1206  */
1207  if (attr.flags & MAIL_COPY_DELIVERED) {
1208  DELIVERED_HDR_INFO *info;
1209  RECIPIENT *rcpt;
1210  int loop_found;
1211 
1212  if (request->rcpt_list.len > 1)
1213  msg_panic("%s: delivered-to enabled with multi-recipient request",
1214  myname);
1215  info = delivered_hdr_init(request->fp, request->data_offset,
1216  FOLD_ADDR_ALL);
1217  rcpt = request->rcpt_list.info;
1218  loop_found = delivered_hdr_find(info, rcpt->address);
1219  delivered_hdr_free(info);
1220  if (loop_found) {
1221  dsb_simple(why, "5.4.6", "mail forwarding loop for %s",
1222  rcpt->address);
1223  deliver_status = eval_command_status(PIPE_STAT_BOUNCE, service,
1224  request, &attr, why);
1226  return (deliver_status);
1227  }
1228  }
1229 
1230  /*
1231  * Deliver. Set the nexthop and sender variables, and expand the command
1232  * argument vector. Recipients will be expanded on the fly. XXX Rewrite
1233  * envelope and header addresses according to transport-specific
1234  * rewriting rules.
1235  */
1236  if (vstream_fseek(request->fp, request->data_offset, SEEK_SET) < 0)
1237  msg_fatal("seek queue file %s: %m", VSTREAM_PATH(request->fp));
1238 
1239  /*
1240  * A non-empty null sender replacement is subject to the 'q' flag.
1241  */
1242  buf = vstring_alloc(10);
1243  sender = *request->sender ? request->sender : STR(attr.null_sender);
1244  if (*sender && (attr.flags & PIPE_OPT_QUOTE_LOCAL)) {
1245  quote_822_local(buf, sender);
1247  } else
1249  if (attr.flags & PIPE_OPT_FOLD_HOST) {
1250  casefold(buf, request->nexthop);
1252  } else
1254  vstring_sprintf(buf, "%ld", (long) request->data_size);
1257  request->client_addr);
1259  request->client_helo);
1261  request->client_name);
1263  request->client_port);
1265  request->client_proto);
1267  request->sasl_method);
1269  request->sasl_username);
1271  request->sasl_sender);
1273  request->queue_id);
1274  vstring_free(buf);
1275 
1276  if ((expanded_argv = expand_argv(service, attr.command,
1277  rcpt_list, attr.flags)) == 0) {
1278  dsb_simple(why, "4.3.5", "mail system configuration error");
1279  deliver_status = eval_command_status(PIPE_STAT_DEFER, service,
1280  request, &attr, why);
1282  return (deliver_status);
1283  }
1285 
1286  command_status = pipe_command(request->fp, why,
1287  CA_PIPE_CMD_UID(attr.uid),
1288  CA_PIPE_CMD_GID(attr.gid),
1289  CA_PIPE_CMD_SENDER(sender),
1291  CA_PIPE_CMD_ARGV(expanded_argv->argv),
1293  CA_PIPE_CMD_EOL(STR(attr.eol)),
1294  CA_PIPE_CMD_EXPORT(export_env->argv),
1295  CA_PIPE_CMD_CWD(attr.exec_dir),
1297  CA_PIPE_CMD_ORIG_RCPT(rcpt_list->info[0].orig_addr),
1298  CA_PIPE_CMD_DELIVERED(rcpt_list->info[0].address),
1299  CA_PIPE_CMD_END);
1300  argv_free(export_env);
1301 
1302  deliver_status = eval_command_status(command_status, service, request,
1303  &attr, why);
1304 
1305  /*
1306  * Clean up.
1307  */
1309 
1310  return (deliver_status);
1311 }
1312 
1313 /* pipe_service - perform service for client */
1314 
1315 static void pipe_service(VSTREAM *client_stream, char *service, char **argv)
1316 {
1317  DELIVER_REQUEST *request;
1318  int status;
1319 
1320  /*
1321  * This routine runs whenever a client connects to the UNIX-domain socket
1322  * dedicated to delivery via external command. What we see below is a
1323  * little protocol to (1) tell the queue manager that we are ready, (2)
1324  * read a request from the queue manager, and (3) report the completion
1325  * status of that request. All connection-management stuff is handled by
1326  * the common code in single_server.c.
1327  */
1328  if ((request = deliver_request_read(client_stream)) != 0) {
1329  status = deliver_message(request, service, argv);
1330  deliver_request_done(client_stream, request, status);
1331  }
1332 }
1333 
1334 /* pre_accept - see if tables have changed */
1335 
1336 static void pre_accept(char *unused_name, char **unused_argv)
1337 {
1338  const char *table;
1339 
1340  if ((table = dict_changed_name()) != 0) {
1341  msg_info("table %s has changed -- restarting", table);
1342  exit(0);
1343  }
1344 }
1345 
1346 /* drop_privileges - drop privileges most of the time */
1347 
1348 static void drop_privileges(char *unused_name, char **unused_argv)
1349 {
1351 }
1352 
1353 /* pre_init - initialize */
1354 
1355 static void pre_init(char *unused_name, char **unused_argv)
1356 {
1357  flush_init();
1358 }
1359 
1361 
1362 /* main - pass control to the single-threaded skeleton */
1363 
1364 int main(int argc, char **argv)
1365 {
1366  static const CONFIG_TIME_TABLE time_table[] = {
1368  0,
1369  };
1370  static const CONFIG_STR_TABLE str_table[] = {
1372  0,
1373  };
1374 
1375  /*
1376  * Fingerprint executables and core dumps.
1377  */
1379 
1380  single_server_main(argc, argv, pipe_service,
1381  CA_MAIL_SERVER_TIME_TABLE(time_table),
1382  CA_MAIL_SERVER_STR_TABLE(str_table),
1383  CA_MAIL_SERVER_PRE_INIT(pre_init),
1384  CA_MAIL_SERVER_POST_INIT(drop_privileges),
1385  CA_MAIL_SERVER_PRE_ACCEPT(pre_accept),
1389  0);
1390 }
int msg_verbose
Definition: msg.c:177
const char * orig_addr
int flags
Definition: pipe.c:596
#define PIPE_OPT_FOLD_FLAGS(f)
Definition: pipe.c:563
void myfree(void *ptr)
Definition: mymalloc.c:207
char * chroot_dir
Definition: pipe.c:598
gid_t gid
Definition: pipe.c:595
#define MAIL_COPY_QUOTE
Definition: mail_copy.h:32
#define CA_PIPE_CMD_DELIVERED(v)
Definition: pipe_command.h:55
RECIPIENT_LIST rcpt_list
#define CA_PIPE_CMD_CWD(v)
Definition: pipe_command.h:64
#define ARGV_END
Definition: argv.h:52
DSN_BUF * dsb_create(void)
Definition: dsn_buf.c:169
#define PIPE_STAT_DEFER
Definition: pipe_command.h:77
char * mystrdup(const char *str)
Definition: mymalloc.c:225
const char * service
Definition: pipe.c:608
#define PIPE_FLAG_EXTENSION
Definition: pipe.c:547
#define PIPE_DICT_EXTENSION
Definition: pipe.c:527
#define PIPE_DICT_RCPT
Definition: pipe.c:523
#define PIPE_DICT_ORIG_RCPT
Definition: pipe.c:524
ARGV * argv_free(ARGV *argvp)
Definition: argv.c:136
#define MAIL_COPY_DOT
Definition: mail_copy.h:37
const char * address
Definition: argv.h:17
off_t size_limit
Definition: pipe.c:601
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
#define CA_MAIL_SERVER_STR_TABLE(v)
Definition: mail_server.h:57
DSN_BUF * dsb_update(DSN_BUF *dsb, const char *status, const char *action, const char *mtype, const char *mname, const char *dtype, const char *dtext, const char *format,...)
Definition: dsn_buf.c:239
#define DEL_REQ_FLAG_SUCCESS
#define vstring_str(vp)
Definition: vstring.h:71
#define PIPE_FLAG_USER
Definition: pipe.c:546
void deliver_completed(VSTREAM *stream, long offset)
int delivered_hdr_find(DELIVERED_HDR_INFO *info, const char *address)
off_t off_cvt_string(const char *str)
Definition: off_cvt.c:71
char ** command
Definition: pipe.c:593
#define PIPE_FLAG_RCPT
Definition: pipe.c:545
char * var_sgid_group
Definition: mail_params.c:236
#define PIPE_FLAG_ORIG_RCPT
Definition: pipe.c:550
#define PIPE_STAT_OK
Definition: pipe_command.h:76
#define STR
Definition: pipe.c:615
#define MAIL_COPY_RETURN_PATH
Definition: mail_copy.h:36
char ** argv
Definition: argv.h:20
#define DEL_REQ_TRACE_ONLY(f)
DSN dsn
Definition: dsn_buf.h:28
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
Definition: vstring.c:415
#define split_addr
Definition: split_addr.h:20
#define VSTREAM_PATH(vp)
Definition: vstream.h:126
void argv_add(ARGV *argvp,...)
Definition: argv.c:197
char * var_config_dir
Definition: mail_params.c:241
#define DSB_SKIP_RMTA
Definition: dsn_buf.h:42
char * var_pipe_dsn_filter
Definition: pipe.c:575
#define PIPE_DICT_CLIENT_NAME
Definition: pipe.c:532
#define DEF_PIPE_DSN_FILTER
Definition: mail_params.h:3987
#define CA_PIPE_CMD_UID(v)
Definition: pipe_command.h:56
MAIL_VERSION_STAMP_DECLARE
Definition: pipe.c:1360
ARGV * argv_alloc(ssize_t len)
Definition: argv.c:149
#define CA_MAIL_SERVER_BOUNCE_INIT(v, w)
Definition: mail_server.h:76
#define VSTRING_LEN(vp)
Definition: vstring.h:72
#define CA_PIPE_CMD_COPY_FLAGS(v)
Definition: pipe_command.h:53
#define PIPE_STAT_CORRUPT
Definition: pipe_command.h:79
void flush_init(void)
Definition: flush_clnt.c:104
VSTRING * eol
Definition: pipe.c:599
int strncasecmp(const char *s1, const char *s2, size_t n)
Definition: strcasecmp.c:52
gid_t var_sgid_gid
Definition: mail_params.c:237
#define DEL_REQ_TRACE_FLAGS(f)
MSG_STATS msg_stats
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
Definition: vstring.c:431
#define VAR_PIPE_DSN_FILTER
Definition: mail_params.h:3986
#define casefold(dst, src)
Definition: stringops.h:67
int bounce_append(int flags, const char *id, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn)
Definition: bounce.c:222
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
#define MAIL_COPY_BLANK
Definition: mail_copy.h:38
char * var_rcpt_delim
Definition: mail_params.c:274
#define DSB_SKIP_REPLY
Definition: dsn_buf.h:46
#define _MAXTIME
Definition: mail_params.h:546
#define VAR_EXPORT_ENVIRON
Definition: mail_params.h:2510
#define CA_MAIL_SERVER_POST_INIT(v)
Definition: mail_server.h:65
int pipe_command(VSTREAM *src, DSN_BUF *why,...)
Definition: pipe_command.c:389
#define EARLY_RETURN(x)
gid_t var_owner_gid
Definition: mail_params.c:235
ARGV * mail_parm_split(const char *name, const char *value)
uid_t var_owner_uid
Definition: mail_params.c:234
#define PIPE_FLAG_DOMAIN
Definition: pipe.c:549
#define PIPE_DICT_CLIENT_PROTO
Definition: pipe.c:534
#define NO
#define DSN_FROM_DSN_BUF(dsb)
Definition: dsn_buf.h:68
const char * dict_changed_name(void)
Definition: dict.c:583
#define CA_PIPE_CMD_END
Definition: pipe_command.h:50
int expand_flag
Definition: pipe.c:609
#define CA_PIPE_CMD_EOL(v)
Definition: pipe_command.h:61
char * fold_addr(VSTRING *result, const char *addr, int flags)
Definition: fold_addr.c:67
#define MASTER_CONF_FILE
Definition: mail_params.h:335
#define DEF_COMMAND_MAXTIME
Definition: mail_params.h:547
#define CA_PIPE_CMD_GID(v)
Definition: pipe_command.h:57
#define MAIL_COPY_FROM
Definition: mail_copy.h:34
#define MAIL_ADDR_MAIL_DAEMON
Definition: mail_addr.h:18
int get_mail_conf_time2(const char *, const char *, int, int, int, int)
#define PIPE_DICT_SIZE
Definition: pipe.c:530
void msg_warn(const char *fmt,...)
Definition: msg.c:215
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
#define PIPE_DICT_USER
Definition: pipe.c:526
#define DELIVER_MSG_CLEANUP()
#define CA_PIPE_CMD_TIME_LIMIT(v)
Definition: pipe_command.h:58
#define VAR_COMMAND_MAXTIME
Definition: mail_params.h:545
#define MAIL_VERSION_STAMP_ALLOCATE
Definition: mail_version.h:67
#define PIPE_DICT_QUEUE_ID
Definition: pipe.c:539
#define PIPE_DICT_SASL_SENDER
Definition: pipe.c:538
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
Definition: vstring.c:602
#define PIPE_DICT_MAILBOX
Definition: pipe.c:528
#define CA_MAIL_SERVER_TIME_TABLE(v)
Definition: mail_server.h:59
int main(int argc, char **argv)
Definition: pipe.c:1364
DSN_BUF * dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
Definition: dsn_buf.c:275
#define MAIL_COPY_DELIVERED
Definition: mail_copy.h:35
#define PIPE_DICT_SASL_METHOD
Definition: pipe.c:536
char * trimblanks(char *, ssize_t)
Definition: trimblanks.c:37
DELIVERED_HDR_INFO * delivered_hdr_init(VSTREAM *fp, off_t offset, int flags)
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
off_t vstream_fseek(VSTREAM *stream, off_t offset, int whence)
Definition: vstream.c:1093
int dict_update(const char *dict_name, const char *member, const char *value)
Definition: dict.c:369
#define CA_MAIL_SERVER_PRIVILEGED
Definition: mail_server.h:72
#define DEL_STAT_DEFER
int mac_parse(const char *value, MAC_PARSE_FN action, void *context)
Definition: mac_parse.c:85
void set_eugid(uid_t euid, gid_t egid)
Definition: set_eugid.c:54
int deliver_request_done(VSTREAM *stream, DELIVER_REQUEST *request, int status)
#define FOLD_ADDR_ALL
Definition: fold_addr.h:20
int var_command_maxtime
Definition: pipe.c:570
#define PIPE_DICT_NEXTHOP
Definition: pipe.c:522
#define PIPE_DICT_CLIENT_ADDR
Definition: pipe.c:531
#define CA_PIPE_CMD_ORIG_RCPT(v)
Definition: pipe_command.h:63
#define CA_PIPE_CMD_CHROOT(v)
Definition: pipe_command.h:65
const char * dict_eval(const char *dict_name, const char *value, int recursive)
Definition: dict.c:536
#define PIPE_DICT_DOMAIN
Definition: pipe.c:529
#define PIPE_DICT_TABLE
Definition: pipe.c:521
VSTRING * reason
Definition: dsn_buf.h:37
#define quote_822_local(dst, src)
#define CA_PIPE_CMD_SENDER(v)
Definition: pipe_command.h:54
#define CA_PIPE_CMD_ARGV(v)
Definition: pipe_command.h:52
#define PIPE_DICT_SENDER
Definition: pipe.c:525
#define PIPE_OPT_FOLD_USER
Definition: pipe.c:557
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
RECIPIENT * info
char * var_mail_owner
Definition: mail_params.c:233
VSTRING * null_sender
Definition: pipe.c:600
#define PIPE_FLAG_MAILBOX
Definition: pipe.c:548
int time_limit
Definition: pipe.c:586
NORETURN single_server_main(int, char **, SINGLE_SERVER_FN,...)
char * split_at(char *string, int delimiter)
Definition: split_at.c:53
#define MAC_PARSE_VARNAME
Definition: mac_parse.h:24
char * var_export_environ
Definition: mail_params.c:297
int defer_append(int flags, const char *id, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn)
Definition: defer.c:187
#define PIPE_DICT_CLIENT_PORT
Definition: pipe.c:533
char * exec_dir
Definition: pipe.c:597
#define PIPE_DICT_SASL_USERNAME
Definition: pipe.c:537
#define PIPE_STAT_BOUNCE
Definition: pipe_command.h:78
#define MAIL_COPY_ORIG_RCPT
Definition: mail_copy.h:39
#define PIPE_DICT_CLIENT_HELO
Definition: pipe.c:535
#define CA_MAIL_SERVER_PRE_ACCEPT(v)
Definition: mail_server.h:68
int sent(int flags, const char *id, MSG_STATS *stats, RECIPIENT *recipient, const char *relay, DSN *dsn)
Definition: sent.c:95
uid_t uid
Definition: pipe.c:594
DELIVER_REQUEST * deliver_request_read(VSTREAM *stream)
#define CA_PIPE_CMD_EXPORT(v)
Definition: pipe_command.h:62
VSTRING * status
Definition: dsn_buf.h:30
#define PIPE_OPT_FOLD_HOST
Definition: pipe.c:558
char * split_at_right(char *string, int delimiter)
Definition: split_at.c:64
#define PIPE_OPT_QUOTE_LOCAL
Definition: pipe.c:559
#define PIPE_OPT_FOLD_ALL
Definition: pipe.c:562
char * vstring_export(VSTRING *vp)
Definition: vstring.c:569
#define PIPE_OPT_FINAL_DELIVERY
Definition: pipe.c:560
void delivered_hdr_free(DELIVERED_HDR_INFO *info)
#define CA_MAIL_SERVER_PRE_INIT(v)
Definition: mail_server.h:64
#define MAC_PARSE_ERROR
Definition: mac_parse.h:27
void argv_terminate(ARGV *argvp)
Definition: argv.c:242
VSTRING * unescape(VSTRING *, const char *)
Definition: unescape.c:69
void msg_info(const char *fmt,...)
Definition: msg.c:199