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