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