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