1 /* $NetBSD: pickup.c,v 1.1.1.4 2011/03/02 19:32:24 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 || *reason == 0) 202 msg_warn("%s: error writing %s: %s", 203 info->path, info->id, cleanup_strerror(status)); 204 return ((status & (CLEANUP_STAT_BAD | CLEANUP_STAT_RCPT)) ? 205 REMOVE_MESSAGE_FILE : KEEP_MESSAGE_FILE); 206 } 207 208 #define cleanup_service_error(info, status) \ 209 cleanup_service_error_reason((info), (status), (char *) 0) 210 211 /* copy_segment - copy a record group */ 212 213 static int copy_segment(VSTREAM *qfile, VSTREAM *cleanup, PICKUP_INFO *info, 214 VSTRING *buf, char *expected) 215 { 216 int type; 217 int check_first = (*expected == REC_TYPE_CONTENT[0]); 218 int time_seen = 0; 219 char *attr_name; 220 char *attr_value; 221 char *saved_attr; 222 int skip_attr; 223 224 /* 225 * Limit the input record size. All front-end programs should protect the 226 * mail system against unreasonable inputs. This also requires that we 227 * limit the size of envelope records written by the local posting agent. 228 * 229 * Records with named attributes are filtered by postdrop(1). 230 * 231 * We must allow PTR records here because of "postsuper -r". 232 */ 233 for (;;) { 234 if ((type = rec_get(qfile, buf, var_line_limit)) < 0 235 || strchr(expected, type) == 0) 236 return (file_read_error(info, type)); 237 if (msg_verbose) 238 msg_info("%s: read %c %s", info->id, type, vstring_str(buf)); 239 if (type == *expected) 240 break; 241 if (type == REC_TYPE_FROM) { 242 if (info->sender == 0) 243 info->sender = mystrdup(vstring_str(buf)); 244 /* Compatibility with Postfix < 2.3. */ 245 if (time_seen == 0) 246 rec_fprintf(cleanup, REC_TYPE_TIME, "%ld", 247 (long) info->st.st_mtime); 248 } 249 if (type == REC_TYPE_TIME) 250 time_seen = 1; 251 252 /* 253 * XXX Workaround: REC_TYPE_FILT (used in envelopes) == REC_TYPE_CONT 254 * (used in message content). 255 * 256 * As documented in postsuper(1), ignore content filter record. 257 */ 258 if (*expected != REC_TYPE_CONTENT[0]) { 259 if (type == REC_TYPE_FILT) 260 /* Discard FILTER record after "postsuper -r". */ 261 continue; 262 if (type == REC_TYPE_RDR) 263 /* Discard REDIRECT record after "postsuper -r". */ 264 continue; 265 } 266 if (*expected == REC_TYPE_EXTRACT[0]) { 267 if (type == REC_TYPE_RRTO) 268 /* Discard return-receipt record after "postsuper -r". */ 269 continue; 270 if (type == REC_TYPE_ERTO) 271 /* Discard errors-to record after "postsuper -r". */ 272 continue; 273 if (type == REC_TYPE_ATTR) { 274 saved_attr = mystrdup(vstring_str(buf)); 275 skip_attr = (split_nameval(saved_attr, 276 &attr_name, &attr_value) == 0 277 && rec_attr_map(attr_name) == 0); 278 myfree(saved_attr); 279 /* Discard other/header/body action after "postsuper -r". */ 280 if (skip_attr) 281 continue; 282 } 283 } 284 285 /* 286 * XXX Force an empty record when the queue file content begins with 287 * whitespace, so that it won't be considered as being part of our 288 * own Received: header. What an ugly Kluge. 289 */ 290 if (check_first 291 && (type == REC_TYPE_NORM || type == REC_TYPE_CONT)) { 292 check_first = 0; 293 if (VSTRING_LEN(buf) > 0 && IS_SPACE_TAB(vstring_str(buf)[0])) 294 rec_put(cleanup, REC_TYPE_NORM, "", 0); 295 } 296 if ((REC_PUT_BUF(cleanup, type, buf)) < 0) 297 return (cleanup_service_error(info, CLEANUP_STAT_WRITE)); 298 } 299 return (0); 300 } 301 302 /* pickup_copy - copy message to cleanup service */ 303 304 static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup, 305 PICKUP_INFO *info, VSTRING *buf) 306 { 307 time_t now = time((time_t *) 0); 308 int status; 309 char *name; 310 311 /* 312 * Protect against time-warped time stamps. Warn about mail that has been 313 * queued for an excessive amount of time. Allow for some time drift with 314 * network clients that mount the maildrop remotely - especially clients 315 * that can't get their daylight savings offsets right. 316 */ 317 #define DAY_SECONDS 86400 318 #define HOUR_SECONDS 3600 319 320 if (info->st.st_mtime > now + 2 * HOUR_SECONDS) { 321 msg_warn("%s: message dated %ld seconds into the future", 322 info->id, (long) (info->st.st_mtime - now)); 323 info->st.st_mtime = now; 324 } else if (info->st.st_mtime < now - DAY_SECONDS) { 325 msg_warn("%s: message has been queued for %d days", 326 info->id, (int) ((now - info->st.st_mtime) / DAY_SECONDS)); 327 } 328 329 /* 330 * Add content inspection transport. See also postsuper(1). 331 */ 332 if (*var_filter_xport) 333 rec_fprintf(cleanup, REC_TYPE_FILT, "%s", var_filter_xport); 334 335 /* 336 * Copy the message envelope segment. Allow only those records that we 337 * expect to see in the envelope section. The envelope segment must 338 * contain an envelope sender address. 339 */ 340 if ((status = copy_segment(qfile, cleanup, info, buf, REC_TYPE_ENVELOPE)) != 0) 341 return (status); 342 if (info->sender == 0) { 343 msg_warn("%s: uid=%ld: no envelope sender", 344 info->id, (long) info->st.st_uid); 345 return (REMOVE_MESSAGE_FILE); 346 } 347 348 /* 349 * For messages belonging to $mail_owner also log the maildrop queue id. 350 * This supports message tracking for mail requeued via "postsuper -r". 351 */ 352 #define MAIL_IS_REQUEUED(info) \ 353 ((info)->st.st_uid == var_owner_uid && ((info)->st.st_mode & S_IROTH) == 0) 354 355 if (MAIL_IS_REQUEUED(info)) { 356 msg_info("%s: uid=%d from=<%s> orig_id=%s", info->id, 357 (int) info->st.st_uid, info->sender, 358 ((name = strrchr(info->path, '/')) != 0 ? 359 name + 1 : info->path)); 360 } else { 361 msg_info("%s: uid=%d from=<%s>", info->id, 362 (int) info->st.st_uid, info->sender); 363 } 364 365 /* 366 * Message content segment. Send a dummy message length. Prepend a 367 * Received: header to the message contents. For tracing purposes, 368 * include the message file ownership, without revealing the login name. 369 */ 370 rec_fputs(cleanup, REC_TYPE_MESG, ""); 371 rec_fprintf(cleanup, REC_TYPE_NORM, "Received: by %s (%s, from userid %ld)", 372 var_myhostname, var_mail_name, (long) info->st.st_uid); 373 rec_fprintf(cleanup, REC_TYPE_NORM, "\tid %s; %s", info->id, 374 mail_date(info->st.st_mtime)); 375 376 /* 377 * Copy the message content segment. Allow only those records that we 378 * expect to see in the message content section. 379 */ 380 if ((status = copy_segment(qfile, cleanup, info, buf, REC_TYPE_CONTENT)) != 0) 381 return (status); 382 383 /* 384 * Send the segment with information extracted from message headers. 385 * Permit a non-empty extracted segment, so that list manager software 386 * can to output recipients after the message, and so that sysadmins can 387 * re-inject messages after a change of configuration. 388 */ 389 rec_fputs(cleanup, REC_TYPE_XTRA, ""); 390 if ((status = copy_segment(qfile, cleanup, info, buf, REC_TYPE_EXTRACT)) != 0) 391 return (status); 392 393 /* 394 * There are no errors. Send the end-of-data marker, and get the cleanup 395 * service completion status. XXX Since the pickup service is unable to 396 * bounce, the cleanup service can report only soft errors here. 397 */ 398 rec_fputs(cleanup, REC_TYPE_END, ""); 399 if (attr_scan(cleanup, ATTR_FLAG_MISSING, 400 ATTR_TYPE_INT, MAIL_ATTR_STATUS, &status, 401 ATTR_TYPE_STR, MAIL_ATTR_WHY, buf, 402 ATTR_TYPE_END) != 2) 403 return (cleanup_service_error(info, CLEANUP_STAT_WRITE)); 404 405 /* 406 * Depending on the cleanup service completion status, delete the message 407 * file, or try again later. Bounces are dealt with by the cleanup 408 * service itself. The master process wakes up the cleanup service every 409 * now and then. 410 */ 411 if (status) { 412 return (cleanup_service_error_reason(info, status, vstring_str(buf))); 413 } else { 414 return (REMOVE_MESSAGE_FILE); 415 } 416 } 417 418 /* pickup_file - initialize for file copy and cleanup */ 419 420 static int pickup_file(PICKUP_INFO *info) 421 { 422 VSTRING *buf = vstring_alloc(100); 423 int status; 424 VSTREAM *qfile; 425 VSTREAM *cleanup; 426 int cleanup_flags; 427 428 /* 429 * Open the submitted file. If we cannot open it, and we're not having a 430 * file descriptor leak problem, delete the submitted file, so that we 431 * won't keep complaining about the same file again and again. XXX 432 * Perhaps we should save "bad" files elsewhere for further inspection. 433 * XXX How can we delete a file when open() fails with ENOENT? 434 */ 435 qfile = safe_open(info->path, O_RDONLY | O_NONBLOCK, 0, 436 (struct stat *) 0, -1, -1, buf); 437 if (qfile == 0) { 438 if (errno != ENOENT) 439 msg_warn("open input file %s: %s", info->path, vstring_str(buf)); 440 vstring_free(buf); 441 if (errno == EACCES) 442 msg_warn("if this file was created by Postfix < 1.1, then you may have to chmod a+r %s/%s", 443 var_queue_dir, info->path); 444 return (errno == EACCES ? KEEP_MESSAGE_FILE : REMOVE_MESSAGE_FILE); 445 } 446 447 /* 448 * Contact the cleanup service and read the queue ID that it has 449 * allocated. In case of trouble, request that the cleanup service 450 * bounces its copy of the message. because the original input file is 451 * not readable by the bounce service. 452 * 453 * If mail is re-injected with "postsuper -r", disable Milter applications. 454 * If they were run before the mail was queued then there is no need to 455 * run them again. Moreover, the queue file does not contain enough 456 * information to reproduce the exact same SMTP events and Sendmail 457 * macros that Milters received when the mail originally arrived in 458 * Postfix. 459 * 460 * The actual message copying code is in a separate routine, so that it is 461 * easier to implement the many possible error exits without forgetting 462 * to close files, or to release memory. 463 */ 464 cleanup_flags = 465 input_transp_cleanup(CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_MASK_EXTERNAL, 466 pickup_input_transp_mask); 467 /* As documented in postsuper(1). */ 468 if (MAIL_IS_REQUEUED(info)) 469 cleanup_flags &= ~CLEANUP_FLAG_MILTER; 470 471 cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service); 472 if (attr_scan(cleanup, ATTR_FLAG_STRICT, 473 ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, buf, 474 ATTR_TYPE_END) != 1 475 || attr_print(cleanup, ATTR_FLAG_NONE, 476 ATTR_TYPE_INT, MAIL_ATTR_FLAGS, cleanup_flags, 477 ATTR_TYPE_END) != 0) { 478 status = KEEP_MESSAGE_FILE; 479 } else { 480 info->id = mystrdup(vstring_str(buf)); 481 status = pickup_copy(qfile, cleanup, info, buf); 482 } 483 vstream_fclose(qfile); 484 vstream_fclose(cleanup); 485 vstring_free(buf); 486 return (status); 487 } 488 489 /* pickup_init - init info structure */ 490 491 static void pickup_init(PICKUP_INFO *info) 492 { 493 info->id = 0; 494 info->path = 0; 495 info->sender = 0; 496 } 497 498 /* pickup_free - wipe info structure */ 499 500 static void pickup_free(PICKUP_INFO *info) 501 { 502 #define SAFE_FREE(x) { if (x) myfree(x); } 503 504 SAFE_FREE(info->id); 505 SAFE_FREE(info->path); 506 SAFE_FREE(info->sender); 507 } 508 509 /* pickup_service - service client */ 510 511 static void pickup_service(char *unused_buf, int unused_len, 512 char *unused_service, char **argv) 513 { 514 SCAN_DIR *scan; 515 char *queue_name; 516 PICKUP_INFO info; 517 const char *path; 518 char *id; 519 int file_count; 520 521 /* 522 * Sanity check. This service takes no command-line arguments. 523 */ 524 if (argv[0]) 525 msg_fatal("unexpected command-line argument: %s", argv[0]); 526 527 /* 528 * Skip over things that we don't want to open, such as files that are 529 * still being written, or garbage. Leave it up to the sysadmin to remove 530 * garbage. Keep scanning the queue directory until we stop removing 531 * files from it. 532 * 533 * When we find a file, stroke the watchdog so that it will not bark while 534 * some application is keeping us busy by injecting lots of mail into the 535 * maildrop directory. 536 */ 537 queue_name = MAIL_QUEUE_MAILDROP; /* XXX should be a list */ 538 do { 539 file_count = 0; 540 scan = scan_dir_open(queue_name); 541 while ((id = scan_dir_next(scan)) != 0) { 542 if (mail_open_ok(queue_name, id, &info.st, &path) == MAIL_OPEN_YES) { 543 pickup_init(&info); 544 info.path = mystrdup(path); 545 watchdog_pat(); 546 if (pickup_file(&info) == REMOVE_MESSAGE_FILE) { 547 if (REMOVE(info.path)) 548 msg_warn("remove %s: %m", info.path); 549 else 550 file_count++; 551 } 552 pickup_free(&info); 553 } 554 } 555 scan_dir_close(scan); 556 } while (file_count); 557 } 558 559 /* post_jail_init - drop privileges */ 560 561 static void post_jail_init(char *unused_name, char **unused_argv) 562 { 563 564 /* 565 * In case master.cf was not updated for unprivileged service. 566 */ 567 if (getuid() != var_owner_uid) 568 set_ugid(var_owner_uid, var_owner_gid); 569 570 /* 571 * Initialize the receive transparency options: do we want unknown 572 * recipient checks, do we want address mapping. 573 */ 574 pickup_input_transp_mask = 575 input_transp_mask(VAR_INPUT_TRANSP, var_input_transp); 576 } 577 578 MAIL_VERSION_STAMP_DECLARE; 579 580 /* main - pass control to the multi-threaded server skeleton */ 581 582 int main(int argc, char **argv) 583 { 584 static const CONFIG_STR_TABLE str_table[] = { 585 VAR_FILTER_XPORT, DEF_FILTER_XPORT, &var_filter_xport, 0, 0, 586 VAR_INPUT_TRANSP, DEF_INPUT_TRANSP, &var_input_transp, 0, 0, 587 0, 588 }; 589 590 /* 591 * Fingerprint executables and core dumps. 592 */ 593 MAIL_VERSION_STAMP_ALLOCATE; 594 595 /* 596 * Use the multi-threaded skeleton, because no-one else should be 597 * monitoring our service socket while this process runs. 598 * 599 * XXX The default watchdog timeout for trigger servers is 1000s, while the 600 * cleanup server watchdog timeout is $daemon_timeout (i.e. several 601 * hours). We override the default 1000s timeout to avoid problems with 602 * slow mail submission. The real problem is of course that the 603 * single-threaded pickup server is not a good solution for mail 604 * submissions. 605 */ 606 trigger_server_main(argc, argv, pickup_service, 607 MAIL_SERVER_STR_TABLE, str_table, 608 MAIL_SERVER_POST_INIT, post_jail_init, 609 MAIL_SERVER_SOLITARY, 610 MAIL_SERVER_WATCHDOG, &var_daemon_timeout, 611 0); 612 } 613