1/*++ 2/* NAME 3/* pickup 8 4/* SUMMARY 5/* Postfix local mail pickup 6/* SYNOPSIS 7/* \fBpickup\fR [generic Postfix daemon options] 8/* DESCRIPTION 9/* The \fBpickup\fR(8) daemon waits for hints that new mail has been 10/* dropped into the \fBmaildrop\fR directory, and feeds it into the 11/* \fBcleanup\fR(8) daemon. 12/* Ill-formatted files are deleted without notifying the originator. 13/* This program expects to be run from the \fBmaster\fR(8) process 14/* manager. 15/* STANDARDS 16/* .ad 17/* .fi 18/* None. The \fBpickup\fR(8) daemon does not interact with 19/* the outside world. 20/* SECURITY 21/* .ad 22/* .fi 23/* The \fBpickup\fR(8) daemon is moderately security sensitive. It runs 24/* with fixed low privilege and can run in a chrooted environment. 25/* However, the program reads files from potentially hostile users. 26/* The \fBpickup\fR(8) daemon opens no files for writing, is careful about 27/* what files it opens for reading, and does not actually touch any data 28/* that is sent to its public service endpoint. 29/* DIAGNOSTICS 30/* Problems and transactions are logged to \fBsyslogd\fR(8). 31/* BUGS 32/* The \fBpickup\fR(8) daemon copies mail from file to the \fBcleanup\fR(8) 33/* daemon. It could avoid message copying overhead by sending a file 34/* descriptor instead of file data, but then the already complex 35/* \fBcleanup\fR(8) daemon would have to deal with unfiltered user data. 36/* CONFIGURATION PARAMETERS 37/* .ad 38/* .fi 39/* As the \fBpickup\fR(8) daemon is a relatively long-running process, up 40/* to an hour may pass before a \fBmain.cf\fR change takes effect. 41/* Use the command "\fBpostfix reload\fR" command to speed up a change. 42/* 43/* The text below provides only a parameter summary. See 44/* \fBpostconf\fR(5) for more details including examples. 45/* CONTENT INSPECTION CONTROLS 46/* .ad 47/* .fi 48/* .IP "\fBcontent_filter (empty)\fR" 49/* After the message is queued, send the entire message to the 50/* specified \fItransport:destination\fR. 51/* .IP "\fBreceive_override_options (empty)\fR" 52/* Enable or disable recipient validation, built-in content 53/* filtering, or address mapping. 54/* MISCELLANEOUS CONTROLS 55/* .ad 56/* .fi 57/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" 58/* The default location of the Postfix main.cf and master.cf 59/* configuration files. 60/* .IP "\fBipc_timeout (3600s)\fR" 61/* The time limit for sending or receiving information over an internal 62/* communication channel. 63/* .IP "\fBline_length_limit (2048)\fR" 64/* Upon input, long lines are chopped up into pieces of at most 65/* this length; upon delivery, long lines are reconstructed. 66/* .IP "\fBmax_idle (100s)\fR" 67/* The maximum amount of time that an idle Postfix daemon process waits 68/* for an incoming connection before terminating voluntarily. 69/* .IP "\fBmax_use (100)\fR" 70/* The maximal number of incoming connections that a Postfix daemon 71/* process will service before terminating voluntarily. 72/* .IP "\fBprocess_id (read-only)\fR" 73/* The process ID of a Postfix command or daemon process. 74/* .IP "\fBprocess_name (read-only)\fR" 75/* The process name of a Postfix command or daemon process. 76/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" 77/* The location of the Postfix top-level queue directory. 78/* .IP "\fBsyslog_facility (mail)\fR" 79/* The syslog facility of Postfix logging. 80/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" 81/* The mail system name that is prepended to the process name in syslog 82/* records, so that "smtpd" becomes, for example, "postfix/smtpd". 83/* SEE ALSO 84/* cleanup(8), message canonicalization 85/* sendmail(1), Sendmail-compatible interface 86/* postdrop(1), mail posting agent 87/* postconf(5), configuration parameters 88/* master(5), generic daemon options 89/* master(8), process manager 90/* syslogd(8), system logging 91/* LICENSE 92/* .ad 93/* .fi 94/* The Secure Mailer license must be distributed with this software. 95/* AUTHOR(S) 96/* Wietse Venema 97/* IBM T.J. Watson Research 98/* P.O. Box 704 99/* Yorktown Heights, NY 10598, USA 100/*--*/ 101 102/* System library. */ 103 104#include <sys_defs.h> 105#include <sys/stat.h> 106#include <dirent.h> 107#include <unistd.h> 108#include <stdlib.h> 109#include <time.h> 110#include <string.h> 111#include <fcntl.h> 112#include <errno.h> 113#include <ctype.h> 114 115/* Utility library. */ 116 117#include <msg.h> 118#include <scan_dir.h> 119#include <vstring.h> 120#include <vstream.h> 121#include <set_ugid.h> 122#include <safe_open.h> 123#include <watchdog.h> 124#include <stringops.h> 125 126/* Global library. */ 127 128#include <mail_queue.h> 129#include <mail_open_ok.h> 130#include <mymalloc.h> 131#include <mail_proto.h> 132#include <cleanup_user.h> 133#include <mail_date.h> 134#include <mail_params.h> 135#include <mail_conf.h> 136#include <record.h> 137#include <rec_type.h> 138#include <lex_822.h> 139#include <input_transp.h> 140#include <rec_attr_map.h> 141#include <mail_version.h> 142 143/* Single-threaded server skeleton. */ 144 145#include <mail_server.h> 146 147/* Application-specific. */ 148 149char *var_filter_xport; 150char *var_input_transp; 151 152 /* 153 * Structure to bundle a bunch of information about a queue file. 154 */ 155typedef struct { 156 char *id; /* queue file basename */ 157 struct stat st; /* queue file status */ 158 char *path; /* name for open/remove */ 159 char *sender; /* sender address */ 160} PICKUP_INFO; 161 162 /* 163 * What action should be taken after attempting to deliver a message: remove 164 * the file from the maildrop, or leave it alone. The latter is also used 165 * for files that are still being written to. 166 */ 167#define REMOVE_MESSAGE_FILE 1 168#define KEEP_MESSAGE_FILE 2 169 170 /* 171 * Transparency: before mail is queued, do we allow address mapping, 172 * automatic bcc, header/body checks? 173 */ 174int pickup_input_transp_mask; 175 176/* file_read_error - handle error while reading queue file */ 177 178static int file_read_error(PICKUP_INFO *info, int type) 179{ 180 msg_warn("uid=%ld: unexpected or malformed record type %d", 181 (long) info->st.st_uid, type); 182 return (REMOVE_MESSAGE_FILE); 183} 184 185/* cleanup_service_error_reason - handle error writing to cleanup service. */ 186 187static int cleanup_service_error_reason(PICKUP_INFO *info, int status, 188 const char *reason) 189{ 190 191 /* 192 * XXX If the cleanup server gave a reason, then it was already logged. 193 * Don't bother logging it another time. 194 * 195 * XXX Discard a message without recipient. This can happen with "postsuper 196 * -r" when a message is already delivered (or bounced). The Postfix 197 * sendmail command rejects submissions without recipients. 198 */ 199 if (reason == 0 || *reason == 0) 200 msg_warn("%s: error writing %s: %s", 201 info->path, info->id, cleanup_strerror(status)); 202 return ((status & (CLEANUP_STAT_BAD | CLEANUP_STAT_RCPT)) ? 203 REMOVE_MESSAGE_FILE : KEEP_MESSAGE_FILE); 204} 205 206#define cleanup_service_error(info, status) \ 207 cleanup_service_error_reason((info), (status), (char *) 0) 208 209/* copy_segment - copy a record group */ 210 211static int copy_segment(VSTREAM *qfile, VSTREAM *cleanup, PICKUP_INFO *info, 212 VSTRING *buf, char *expected) 213{ 214 int type; 215 int check_first = (*expected == REC_TYPE_CONTENT[0]); 216 int time_seen = 0; 217 char *attr_name; 218 char *attr_value; 219 char *saved_attr; 220 int skip_attr; 221 222 /* 223 * Limit the input record size. All front-end programs should protect the 224 * mail system against unreasonable inputs. This also requires that we 225 * limit the size of envelope records written by the local posting agent. 226 * 227 * Records with named attributes are filtered by postdrop(1). 228 * 229 * We must allow PTR records here because of "postsuper -r". 230 */ 231 for (;;) { 232 if ((type = rec_get(qfile, buf, var_line_limit)) < 0 233 || strchr(expected, type) == 0) 234 return (file_read_error(info, type)); 235 if (msg_verbose) 236 msg_info("%s: read %c %s", info->id, type, vstring_str(buf)); 237 if (type == *expected) 238 break; 239 if (type == REC_TYPE_FROM) { 240 if (info->sender == 0) 241 info->sender = mystrdup(vstring_str(buf)); 242 /* Compatibility with Postfix < 2.3. */ 243 if (time_seen == 0) 244 rec_fprintf(cleanup, REC_TYPE_TIME, "%ld", 245 (long) info->st.st_mtime); 246 } 247 if (type == REC_TYPE_TIME) 248 time_seen = 1; 249 250 /* 251 * XXX Workaround: REC_TYPE_FILT (used in envelopes) == REC_TYPE_CONT 252 * (used in message content). 253 * 254 * As documented in postsuper(1), ignore content filter record. 255 */ 256 if (*expected != REC_TYPE_CONTENT[0]) { 257 if (type == REC_TYPE_FILT) 258 /* Discard FILTER record after "postsuper -r". */ 259 continue; 260 if (type == REC_TYPE_RDR) 261 /* Discard REDIRECT record after "postsuper -r". */ 262 continue; 263 } 264 if (*expected == REC_TYPE_EXTRACT[0]) { 265 if (type == REC_TYPE_RRTO) 266 /* Discard return-receipt record after "postsuper -r". */ 267 continue; 268 if (type == REC_TYPE_ERTO) 269 /* Discard errors-to record after "postsuper -r". */ 270 continue; 271 if (type == REC_TYPE_ATTR) { 272 saved_attr = mystrdup(vstring_str(buf)); 273 skip_attr = (split_nameval(saved_attr, 274 &attr_name, &attr_value) == 0 275 && rec_attr_map(attr_name) == 0); 276 myfree(saved_attr); 277 /* Discard other/header/body action after "postsuper -r". */ 278 if (skip_attr) 279 continue; 280 } 281 } 282 283 /* 284 * XXX Force an empty record when the queue file content begins with 285 * whitespace, so that it won't be considered as being part of our 286 * own Received: header. What an ugly Kluge. 287 */ 288 if (check_first 289 && (type == REC_TYPE_NORM || type == REC_TYPE_CONT)) { 290 check_first = 0; 291 if (VSTRING_LEN(buf) > 0 && IS_SPACE_TAB(vstring_str(buf)[0])) 292 rec_put(cleanup, REC_TYPE_NORM, "", 0); 293 } 294 if ((REC_PUT_BUF(cleanup, type, buf)) < 0) 295 return (cleanup_service_error(info, CLEANUP_STAT_WRITE)); 296 } 297 return (0); 298} 299 300/* pickup_copy - copy message to cleanup service */ 301 302static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup, 303 PICKUP_INFO *info, VSTRING *buf) 304{ 305 time_t now = time((time_t *) 0); 306 int status; 307 char *name; 308 309 /* 310 * Protect against time-warped time stamps. Warn about mail that has been 311 * queued for an excessive amount of time. Allow for some time drift with 312 * network clients that mount the maildrop remotely - especially clients 313 * that can't get their daylight savings offsets right. 314 */ 315#define DAY_SECONDS 86400 316#define HOUR_SECONDS 3600 317 318 if (info->st.st_mtime > now + 2 * HOUR_SECONDS) { 319 msg_warn("%s: message dated %ld seconds into the future", 320 info->id, (long) (info->st.st_mtime - now)); 321 info->st.st_mtime = now; 322 } else if (info->st.st_mtime < now - DAY_SECONDS) { 323 msg_warn("%s: message has been queued for %d days", 324 info->id, (int) ((now - info->st.st_mtime) / DAY_SECONDS)); 325 } 326 327 /* 328 * Add content inspection transport. See also postsuper(1). 329 */ 330 if (*var_filter_xport) 331 rec_fprintf(cleanup, REC_TYPE_FILT, "%s", var_filter_xport); 332 333 /* 334 * Copy the message envelope segment. Allow only those records that we 335 * expect to see in the envelope section. The envelope segment must 336 * contain an envelope sender address. 337 */ 338 if ((status = copy_segment(qfile, cleanup, info, buf, REC_TYPE_ENVELOPE)) != 0) 339 return (status); 340 if (info->sender == 0) { 341 msg_warn("%s: uid=%ld: no envelope sender", 342 info->id, (long) info->st.st_uid); 343 return (REMOVE_MESSAGE_FILE); 344 } 345 346 /* 347 * For messages belonging to $mail_owner also log the maildrop queue id. 348 * This supports message tracking for mail requeued via "postsuper -r". 349 */ 350#define MAIL_IS_REQUEUED(info) \ 351 ((info)->st.st_uid == var_owner_uid && ((info)->st.st_mode & S_IROTH) == 0) 352 353 if (MAIL_IS_REQUEUED(info)) { 354 msg_info("%s: uid=%d from=<%s> orig_id=%s", info->id, 355 (int) info->st.st_uid, info->sender, 356 ((name = strrchr(info->path, '/')) != 0 ? 357 name + 1 : info->path)); 358 } else { 359 msg_info("%s: uid=%d from=<%s>", info->id, 360 (int) info->st.st_uid, info->sender); 361 } 362 363 /* 364 * Message content segment. Send a dummy message length. Prepend a 365 * Received: header to the message contents. For tracing purposes, 366 * include the message file ownership, without revealing the login name. 367 */ 368 rec_fputs(cleanup, REC_TYPE_MESG, ""); 369 rec_fprintf(cleanup, REC_TYPE_NORM, "Received: by %s (%s, from userid %ld)", 370 var_myhostname, var_mail_name, (long) info->st.st_uid); 371 rec_fprintf(cleanup, REC_TYPE_NORM, "\tid %s; %s", info->id, 372 mail_date(info->st.st_mtime)); 373 374 /* 375 * Copy the message content segment. Allow only those records that we 376 * expect to see in the message content section. 377 */ 378 if ((status = copy_segment(qfile, cleanup, info, buf, REC_TYPE_CONTENT)) != 0) 379 return (status); 380 381 /* 382 * Send the segment with information extracted from message headers. 383 * Permit a non-empty extracted segment, so that list manager software 384 * can to output recipients after the message, and so that sysadmins can 385 * re-inject messages after a change of configuration. 386 */ 387 rec_fputs(cleanup, REC_TYPE_XTRA, ""); 388 if ((status = copy_segment(qfile, cleanup, info, buf, REC_TYPE_EXTRACT)) != 0) 389 return (status); 390 391 /* 392 * There are no errors. Send the end-of-data marker, and get the cleanup 393 * service completion status. XXX Since the pickup service is unable to 394 * bounce, the cleanup service can report only soft errors here. 395 */ 396 rec_fputs(cleanup, REC_TYPE_END, ""); 397 if (attr_scan(cleanup, ATTR_FLAG_MISSING, 398 ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, 399 ATTR_TYPE_STR, MAIL_ATTR_WHY, buf, 400 ATTR_TYPE_END) != 2) 401 return (cleanup_service_error(info, CLEANUP_STAT_WRITE)); 402 403 /* 404 * Depending on the cleanup service completion status, delete the message 405 * file, or try again later. Bounces are dealt with by the cleanup 406 * service itself. The master process wakes up the cleanup service every 407 * now and then. 408 */ 409 if (status) { 410 return (cleanup_service_error_reason(info, status, vstring_str(buf))); 411 } else { 412 return (REMOVE_MESSAGE_FILE); 413 } 414} 415 416/* pickup_file - initialize for file copy and cleanup */ 417 418static int pickup_file(PICKUP_INFO *info) 419{ 420 VSTRING *buf = vstring_alloc(100); 421 int status; 422 VSTREAM *qfile; 423 VSTREAM *cleanup; 424 int cleanup_flags; 425 426 /* 427 * Open the submitted file. If we cannot open it, and we're not having a 428 * file descriptor leak problem, delete the submitted file, so that we 429 * won't keep complaining about the same file again and again. XXX 430 * Perhaps we should save "bad" files elsewhere for further inspection. 431 * XXX How can we delete a file when open() fails with ENOENT? 432 */ 433 qfile = safe_open(info->path, O_RDONLY | O_NONBLOCK, 0, 434 (struct stat *) 0, -1, -1, buf); 435 if (qfile == 0) { 436 if (errno != ENOENT) 437 msg_warn("open input file %s: %s", info->path, vstring_str(buf)); 438 vstring_free(buf); 439 if (errno == EACCES) 440 msg_warn("if this file was created by Postfix < 1.1, then you may have to chmod a+r %s/%s", 441 var_queue_dir, info->path); 442 return (errno == EACCES ? KEEP_MESSAGE_FILE : REMOVE_MESSAGE_FILE); 443 } 444 445 /* 446 * Contact the cleanup service and read the queue ID that it has 447 * allocated. In case of trouble, request that the cleanup service 448 * bounces its copy of the message. because the original input file is 449 * not readable by the bounce service. 450 * 451 * If mail is re-injected with "postsuper -r", disable Milter applications. 452 * If they were run before the mail was queued then there is no need to 453 * run them again. Moreover, the queue file does not contain enough 454 * information to reproduce the exact same SMTP events and Sendmail 455 * macros that Milters received when the mail originally arrived in 456 * Postfix. 457 * 458 * The actual message copying code is in a separate routine, so that it is 459 * easier to implement the many possible error exits without forgetting 460 * to close files, or to release memory. 461 */ 462 cleanup_flags = 463 input_transp_cleanup(CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_MASK_EXTERNAL, 464 pickup_input_transp_mask); 465 /* As documented in postsuper(1). */ 466 if (MAIL_IS_REQUEUED(info)) 467 cleanup_flags &= ~CLEANUP_FLAG_MILTER; 468 469 cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service); 470 if (attr_scan(cleanup, ATTR_FLAG_STRICT, 471 ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, buf, 472 ATTR_TYPE_END) != 1 473 || attr_print(cleanup, ATTR_FLAG_NONE, 474 ATTR_TYPE_INT, MAIL_ATTR_FLAGS, cleanup_flags, 475 ATTR_TYPE_END) != 0) { 476 status = KEEP_MESSAGE_FILE; 477 } else { 478 info->id = mystrdup(vstring_str(buf)); 479 status = pickup_copy(qfile, cleanup, info, buf); 480 } 481 vstream_fclose(qfile); 482 vstream_fclose(cleanup); 483 vstring_free(buf); 484 return (status); 485} 486 487/* pickup_init - init info structure */ 488 489static void pickup_init(PICKUP_INFO *info) 490{ 491 info->id = 0; 492 info->path = 0; 493 info->sender = 0; 494} 495 496/* pickup_free - wipe info structure */ 497 498static void pickup_free(PICKUP_INFO *info) 499{ 500#define SAFE_FREE(x) { if (x) myfree(x); } 501 502 SAFE_FREE(info->id); 503 SAFE_FREE(info->path); 504 SAFE_FREE(info->sender); 505} 506 507/* pickup_service - service client */ 508 509static void pickup_service(char *unused_buf, int unused_len, 510 char *unused_service, char **argv) 511{ 512 SCAN_DIR *scan; 513 char *queue_name; 514 PICKUP_INFO info; 515 const char *path; 516 char *id; 517 int file_count; 518 519 /* 520 * Sanity check. This service takes no command-line arguments. 521 */ 522 if (argv[0]) 523 msg_fatal("unexpected command-line argument: %s", argv[0]); 524 525 /* 526 * Skip over things that we don't want to open, such as files that are 527 * still being written, or garbage. Leave it up to the sysadmin to remove 528 * garbage. Keep scanning the queue directory until we stop removing 529 * files from it. 530 * 531 * When we find a file, stroke the watchdog so that it will not bark while 532 * some application is keeping us busy by injecting lots of mail into the 533 * maildrop directory. 534 */ 535 queue_name = MAIL_QUEUE_MAILDROP; /* XXX should be a list */ 536 do { 537 file_count = 0; 538 scan = scan_dir_open(queue_name); 539 while ((id = scan_dir_next(scan)) != 0) { 540 if (mail_open_ok(queue_name, id, &info.st, &path) == MAIL_OPEN_YES) { 541 pickup_init(&info); 542 info.path = mystrdup(path); 543 watchdog_pat(); 544 if (pickup_file(&info) == REMOVE_MESSAGE_FILE) { 545 if (REMOVE(info.path)) 546 msg_warn("remove %s: %m", info.path); 547 else 548 file_count++; 549 } 550 pickup_free(&info); 551 } 552 } 553 scan_dir_close(scan); 554 } while (file_count); 555} 556 557/* post_jail_init - drop privileges */ 558 559static void post_jail_init(char *unused_name, char **unused_argv) 560{ 561 562 /* 563 * In case master.cf was not updated for unprivileged service. 564 */ 565 if (getuid() != var_owner_uid) 566 set_ugid(var_owner_uid, var_owner_gid); 567 568 /* 569 * Initialize the receive transparency options: do we want unknown 570 * recipient checks, do we want address mapping. 571 */ 572 pickup_input_transp_mask = 573 input_transp_mask(VAR_INPUT_TRANSP, var_input_transp); 574} 575 576MAIL_VERSION_STAMP_DECLARE; 577 578/* main - pass control to the multi-threaded server skeleton */ 579 580int main(int argc, char **argv) 581{ 582 static const CONFIG_STR_TABLE str_table[] = { 583 VAR_FILTER_XPORT, DEF_FILTER_XPORT, &var_filter_xport, 0, 0, 584 VAR_INPUT_TRANSP, DEF_INPUT_TRANSP, &var_input_transp, 0, 0, 585 0, 586 }; 587 588 /* 589 * Fingerprint executables and core dumps. 590 */ 591 MAIL_VERSION_STAMP_ALLOCATE; 592 593 /* 594 * Use the multi-threaded skeleton, because no-one else should be 595 * monitoring our service socket while this process runs. 596 * 597 * XXX The default watchdog timeout for trigger servers is 1000s, while the 598 * cleanup server watchdog timeout is $daemon_timeout (i.e. several 599 * hours). We override the default 1000s timeout to avoid problems with 600 * slow mail submission. The real problem is of course that the 601 * single-threaded pickup server is not a good solution for mail 602 * submissions. 603 */ 604 trigger_server_main(argc, argv, pickup_service, 605 MAIL_SERVER_STR_TABLE, str_table, 606 MAIL_SERVER_POST_INIT, post_jail_init, 607 MAIL_SERVER_SOLITARY, 608 MAIL_SERVER_WATCHDOG, &var_daemon_timeout, 609 0); 610} 611