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 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 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 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 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 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 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 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 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 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 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 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 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