1/*++ 2/* NAME 3/* qmqpd 8 4/* SUMMARY 5/* Postfix QMQP server 6/* SYNOPSIS 7/* \fBqmqpd\fR [generic Postfix daemon options] 8/* DESCRIPTION 9/* The Postfix QMQP server receives one message per connection. 10/* Each message is piped through the \fBcleanup\fR(8) 11/* daemon, and is placed into the \fBincoming\fR queue as one 12/* single queue file. The program expects to be run from the 13/* \fBmaster\fR(8) process manager. 14/* 15/* The QMQP server implements one access policy: only explicitly 16/* authorized client hosts are allowed to use the service. 17/* SECURITY 18/* .ad 19/* .fi 20/* The QMQP server is moderately security-sensitive. It talks to QMQP 21/* clients and to DNS servers on the network. The QMQP server can be 22/* run chrooted at fixed low privilege. 23/* DIAGNOSTICS 24/* Problems and transactions are logged to \fBsyslogd\fR(8). 25/* BUGS 26/* The QMQP protocol provides only one server reply per message 27/* delivery. It is therefore not possible to reject individual 28/* recipients. 29/* 30/* The QMQP protocol requires the server to receive the entire 31/* message before replying. If a message is malformed, or if any 32/* netstring component is longer than acceptable, Postfix replies 33/* immediately and closes the connection. It is left up to the 34/* client to handle the situation. 35/* CONFIGURATION PARAMETERS 36/* .ad 37/* .fi 38/* Changes to \fBmain.cf\fR are picked up automatically, as \fBqmqpd\fR(8) 39/* processes run for only a limited amount of time. Use the command 40/* "\fBpostfix reload\fR" to speed up a change. 41/* 42/* The text below provides only a parameter summary. See 43/* \fBpostconf\fR(5) for more details including examples. 44/* CONTENT INSPECTION CONTROLS 45/* .ad 46/* .fi 47/* .IP "\fBcontent_filter (empty)\fR" 48/* After the message is queued, send the entire message to the 49/* specified \fItransport:destination\fR. 50/* .IP "\fBreceive_override_options (empty)\fR" 51/* Enable or disable recipient validation, built-in content 52/* filtering, or address mapping. 53/* RESOURCE AND RATE CONTROLS 54/* .ad 55/* .fi 56/* .IP "\fBline_length_limit (2048)\fR" 57/* Upon input, long lines are chopped up into pieces of at most 58/* this length; upon delivery, long lines are reconstructed. 59/* .IP "\fBhopcount_limit (50)\fR" 60/* The maximal number of Received: message headers that is allowed 61/* in the primary message headers. 62/* .IP "\fBmessage_size_limit (10240000)\fR" 63/* The maximal size in bytes of a message, including envelope information. 64/* .IP "\fBqmqpd_timeout (300s)\fR" 65/* The time limit for sending or receiving information over the network. 66/* TROUBLE SHOOTING CONTROLS 67/* .ad 68/* .fi 69/* .IP "\fBdebug_peer_level (2)\fR" 70/* The increment in verbose logging level when a remote client or 71/* server matches a pattern in the debug_peer_list parameter. 72/* .IP "\fBdebug_peer_list (empty)\fR" 73/* Optional list of remote client or server hostname or network 74/* address patterns that cause the verbose logging level to increase 75/* by the amount specified in $debug_peer_level. 76/* .IP "\fBsoft_bounce (no)\fR" 77/* Safety net to keep mail queued that would otherwise be returned to 78/* the sender. 79/* TARPIT CONTROLS 80/* .ad 81/* .fi 82/* .IP "\fBqmqpd_error_delay (1s)\fR" 83/* How long the Postfix QMQP server will pause before sending a negative 84/* reply to the remote QMQP client. 85/* MISCELLANEOUS CONTROLS 86/* .ad 87/* .fi 88/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" 89/* The default location of the Postfix main.cf and master.cf 90/* configuration files. 91/* .IP "\fBdaemon_timeout (18000s)\fR" 92/* How much time a Postfix daemon process may take to handle a 93/* request before it is terminated by a built-in watchdog timer. 94/* .IP "\fBipc_timeout (3600s)\fR" 95/* The time limit for sending or receiving information over an internal 96/* communication channel. 97/* .IP "\fBmax_idle (100s)\fR" 98/* The maximum amount of time that an idle Postfix daemon process waits 99/* for an incoming connection before terminating voluntarily. 100/* .IP "\fBmax_use (100)\fR" 101/* The maximal number of incoming connections that a Postfix daemon 102/* process will service before terminating voluntarily. 103/* .IP "\fBprocess_id (read-only)\fR" 104/* The process ID of a Postfix command or daemon process. 105/* .IP "\fBprocess_name (read-only)\fR" 106/* The process name of a Postfix command or daemon process. 107/* .IP "\fBqmqpd_authorized_clients (empty)\fR" 108/* What remote QMQP clients are allowed to connect to the Postfix QMQP 109/* server port. 110/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" 111/* The location of the Postfix top-level queue directory. 112/* .IP "\fBsyslog_facility (mail)\fR" 113/* The syslog facility of Postfix logging. 114/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" 115/* The mail system name that is prepended to the process name in syslog 116/* records, so that "smtpd" becomes, for example, "postfix/smtpd". 117/* .IP "\fBverp_delimiter_filter (-=+)\fR" 118/* The characters Postfix accepts as VERP delimiter characters on the 119/* Postfix \fBsendmail\fR(1) command line and in SMTP commands. 120/* .PP 121/* Available in Postfix version 2.5 and later: 122/* .IP "\fBqmqpd_client_port_logging (no)\fR" 123/* Enable logging of the remote QMQP client port in addition to 124/* the hostname and IP address. 125/* SEE ALSO 126/* http://cr.yp.to/proto/qmqp.html, QMQP protocol 127/* cleanup(8), message canonicalization 128/* master(8), process manager 129/* syslogd(8), system logging 130/* README FILES 131/* .ad 132/* .fi 133/* Use "\fBpostconf readme_directory\fR" or 134/* "\fBpostconf html_directory\fR" to locate this information. 135/* .na 136/* .nf 137/* QMQP_README, Postfix ezmlm-idx howto. 138/* LICENSE 139/* .ad 140/* .fi 141/* The Secure Mailer license must be distributed with this software. 142/* HISTORY 143/* .ad 144/* .fi 145/* The qmqpd service was introduced with Postfix version 1.1. 146/* AUTHOR(S) 147/* Wietse Venema 148/* IBM T.J. Watson Research 149/* P.O. Box 704 150/* Yorktown Heights, NY 10598, USA 151/*--*/ 152 153/* System library. */ 154 155#include <sys_defs.h> 156#include <string.h> 157#include <unistd.h> 158#include <stdlib.h> 159#include <ctype.h> 160#include <stdarg.h> 161 162/* Utility library. */ 163 164#include <msg.h> 165#include <mymalloc.h> 166#include <vstring.h> 167#include <vstream.h> 168#include <netstring.h> 169#include <dict.h> 170#include <inet_proto.h> 171 172/* Global library. */ 173 174#include <mail_params.h> 175#include <mail_version.h> 176#include <record.h> 177#include <rec_type.h> 178#include <mail_proto.h> 179#include <cleanup_user.h> 180#include <mail_date.h> 181#include <mail_conf.h> 182#include <debug_peer.h> 183#include <mail_stream.h> 184#include <namadr_list.h> 185#include <quote_822_local.h> 186#include <match_parent_style.h> 187#include <lex_822.h> 188#include <verp_sender.h> 189#include <input_transp.h> 190 191/* Single-threaded server skeleton. */ 192 193#include <mail_server.h> 194 195/* Application-specific */ 196 197#include <qmqpd.h> 198 199 /* 200 * Tunable parameters. Make sure that there is some bound on the length of a 201 * netstring, so that the mail system stays in control even when a malicious 202 * client sends netstrings of unreasonable length. The recipient count limit 203 * is enforced by the message size limit. 204 */ 205int var_qmqpd_timeout; 206int var_qmqpd_err_sleep; 207char *var_filter_xport; 208char *var_qmqpd_clients; 209char *var_input_transp; 210bool var_qmqpd_client_port_log; 211 212 /* 213 * Silly little macros. 214 */ 215#define STR(x) vstring_str(x) 216#define LEN(x) VSTRING_LEN(x) 217 218#define DO_LOG 1 219#define DONT_LOG 0 220 221 /* 222 * Access control. This service should be exposed only to explicitly 223 * authorized clients. There is no default authorization. 224 */ 225static NAMADR_LIST *qmqpd_clients; 226 227 /* 228 * Transparency: before mail is queued, do we allow address mapping, 229 * automatic bcc, header/body checks? 230 */ 231int qmqpd_input_transp_mask; 232 233/* qmqpd_open_file - open a queue file */ 234 235static void qmqpd_open_file(QMQPD_STATE *state) 236{ 237 int cleanup_flags; 238 239 /* 240 * Connect to the cleanup server. Log client name/address with queue ID. 241 */ 242 cleanup_flags = input_transp_cleanup(CLEANUP_FLAG_MASK_EXTERNAL, 243 qmqpd_input_transp_mask); 244 state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service); 245 if (state->dest == 0 246 || attr_print(state->dest->stream, ATTR_FLAG_NONE, 247 ATTR_TYPE_INT, MAIL_ATTR_FLAGS, cleanup_flags, 248 ATTR_TYPE_END) != 0) 249 msg_fatal("unable to connect to the %s %s service", 250 MAIL_CLASS_PUBLIC, var_cleanup_service); 251 state->cleanup = state->dest->stream; 252 state->queue_id = mystrdup(state->dest->id); 253 msg_info("%s: client=%s", state->queue_id, state->namaddr); 254 255 /* 256 * Record the time of arrival. Optionally, enable content filtering (not 257 * bloody likely, but present for the sake of consistency with all other 258 * Postfix points of entrance). 259 */ 260 rec_fprintf(state->cleanup, REC_TYPE_TIME, REC_TYPE_TIME_FORMAT, 261 REC_TYPE_TIME_ARG(state->arrival_time)); 262 if (*var_filter_xport) 263 rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport); 264} 265 266/* qmqpd_read_content - receive message content */ 267 268static void qmqpd_read_content(QMQPD_STATE *state) 269{ 270 state->where = "receiving message content"; 271 netstring_get(state->client, state->message, var_message_limit); 272} 273 274/* qmqpd_copy_sender - copy envelope sender */ 275 276static void qmqpd_copy_sender(QMQPD_STATE *state) 277{ 278 char *end_prefix; 279 char *end_origin; 280 int verp_requested; 281 static char verp_delims[] = "-="; 282 283 /* 284 * If the sender address looks like prefix@origin-@[], then request 285 * variable envelope return path delivery, with an envelope sender 286 * address of prefi@origin, and with VERP delimiters of x and =. This 287 * way, the recipients will see envelope sender addresses that look like: 288 * prefixuser=domain@origin. 289 */ 290 state->where = "receiving sender address"; 291 netstring_get(state->client, state->buf, var_line_limit); 292 VSTRING_TERMINATE(state->buf); 293 verp_requested = 294 ((end_origin = vstring_end(state->buf) - 4) > STR(state->buf) 295 && strcmp(end_origin, "-@[]") == 0 296 && (end_prefix = strchr(STR(state->buf), '@')) != 0 /* XXX */ 297 && --end_prefix < end_origin - 2 /* non-null origin */ 298 && end_prefix > STR(state->buf)); /* non-null prefix */ 299 if (verp_requested) { 300 verp_delims[0] = end_prefix[0]; 301 if (verp_delims_verify(verp_delims) != 0) { 302 state->err |= CLEANUP_STAT_CONT; /* XXX */ 303 vstring_sprintf(state->why_rejected, "Invalid VERP delimiters: \"%s\". Need two characters from \"%s\"", 304 verp_delims, var_verp_filter); 305 } 306 memmove(end_prefix, end_prefix + 1, end_origin - end_prefix - 1); 307 vstring_truncate(state->buf, end_origin - STR(state->buf) - 1); 308 } 309 if (state->err == CLEANUP_STAT_OK 310 && REC_PUT_BUF(state->cleanup, REC_TYPE_FROM, state->buf) < 0) 311 state->err = CLEANUP_STAT_WRITE; 312 if (verp_requested) 313 if (state->err == CLEANUP_STAT_OK 314 && rec_put(state->cleanup, REC_TYPE_VERP, verp_delims, 2) < 0) 315 state->err = CLEANUP_STAT_WRITE; 316 state->sender = mystrndup(STR(state->buf), LEN(state->buf)); 317} 318 319/* qmqpd_write_attributes - save session attributes */ 320 321static void qmqpd_write_attributes(QMQPD_STATE *state) 322{ 323 324 /* 325 * Logging attributes, also used for XFORWARD. 326 */ 327 rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", 328 MAIL_ATTR_LOG_CLIENT_NAME, state->name); 329 rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", 330 MAIL_ATTR_LOG_CLIENT_ADDR, state->rfc_addr); 331 rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", 332 MAIL_ATTR_LOG_CLIENT_PORT, state->port); 333 rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", 334 MAIL_ATTR_LOG_ORIGIN, state->namaddr); 335 rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", 336 MAIL_ATTR_LOG_PROTO_NAME, state->protocol); 337 338 /* 339 * For consistency with the smtpd Milter client, we need to provide the 340 * real client attributes to the cleanup Milter client. This does not 341 * matter much with qmqpd which speaks to trusted clients only, but we 342 * want to be sure that the cleanup input protocol is ready when a new 343 * type of network daemon is added to receive mail from the Internet. 344 * 345 * See also the comments in smtpd.c. 346 */ 347 rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", 348 MAIL_ATTR_ACT_CLIENT_NAME, state->name); 349 rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", 350 MAIL_ATTR_ACT_CLIENT_ADDR, state->addr); 351 rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", 352 MAIL_ATTR_ACT_CLIENT_PORT, state->port); 353 rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%u", 354 MAIL_ATTR_ACT_CLIENT_AF, state->addr_family); 355 rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", 356 MAIL_ATTR_ACT_PROTO_NAME, state->protocol); 357 358 /* XXX What about the address rewriting context? */ 359} 360 361/* qmqpd_copy_recipients - copy message recipients */ 362 363static void qmqpd_copy_recipients(QMQPD_STATE *state) 364{ 365 int ch; 366 367 /* 368 * Remember the first recipient. We are done when we read the over-all 369 * netstring terminator. 370 * 371 * XXX This approach violates abstractions, but it is a heck of a lot more 372 * convenient than counting the over-all byte count down to zero, like 373 * qmail does. 374 */ 375 state->where = "receiving recipient address"; 376 while ((ch = VSTREAM_GETC(state->client)) != ',') { 377 vstream_ungetc(state->client, ch); 378 netstring_get(state->client, state->buf, var_line_limit); 379 if (state->err == CLEANUP_STAT_OK 380 && REC_PUT_BUF(state->cleanup, REC_TYPE_RCPT, state->buf) < 0) 381 state->err = CLEANUP_STAT_WRITE; 382 state->rcpt_count++; 383 if (state->recipient == 0) 384 state->recipient = mystrndup(STR(state->buf), LEN(state->buf)); 385 } 386} 387 388/* qmqpd_next_line - get line from buffer, return last char, newline, or -1 */ 389 390static int qmqpd_next_line(VSTRING *message, char **start, int *len, 391 char **next) 392{ 393 char *beyond = STR(message) + LEN(message); 394 char *enough = *next + var_line_limit; 395 char *cp; 396 397 /* 398 * Stop at newline or at some limit. Don't look beyond the end of the 399 * buffer. 400 */ 401#define UCHARPTR(x) ((unsigned char *) (x)) 402 403 for (cp = *start = *next; /* void */ ; cp++) { 404 if (cp >= beyond) 405 return ((*len = (*next = cp) - *start) > 0 ? UCHARPTR(cp)[-1] : -1); 406 if (*cp == '\n') 407 return ((*len = cp - *start), (*next = cp + 1), '\n'); 408 if (cp >= enough) 409 return ((*len = cp - *start), (*next = cp), UCHARPTR(cp)[-1]); 410 } 411} 412 413/* qmqpd_write_content - write the message content segment */ 414 415static void qmqpd_write_content(QMQPD_STATE *state) 416{ 417 char *start; 418 char *next; 419 int len; 420 int rec_type; 421 int first = 1; 422 int ch; 423 424 /* 425 * Start the message content segment. Prepend our own Received: header to 426 * the message content. List the recipient only when a message has one 427 * recipient. Otherwise, don't list the recipient to avoid revealing Bcc: 428 * recipients that are supposed to be invisible. 429 */ 430 rec_fputs(state->cleanup, REC_TYPE_MESG, ""); 431 rec_fprintf(state->cleanup, REC_TYPE_NORM, "Received: from %s (%s [%s])", 432 state->name, state->name, state->rfc_addr); 433 if (state->rcpt_count == 1 && state->recipient) { 434 rec_fprintf(state->cleanup, REC_TYPE_NORM, 435 "\tby %s (%s) with %s id %s", 436 var_myhostname, var_mail_name, 437 state->protocol, state->queue_id); 438 quote_822_local(state->buf, state->recipient); 439 rec_fprintf(state->cleanup, REC_TYPE_NORM, 440 "\tfor <%s>; %s", STR(state->buf), 441 mail_date(state->arrival_time.tv_sec)); 442 } else { 443 rec_fprintf(state->cleanup, REC_TYPE_NORM, 444 "\tby %s (%s) with %s", 445 var_myhostname, var_mail_name, state->protocol); 446 rec_fprintf(state->cleanup, REC_TYPE_NORM, 447 "\tid %s; %s", state->queue_id, 448 mail_date(state->arrival_time.tv_sec)); 449 } 450#ifdef RECEIVED_ENVELOPE_FROM 451 quote_822_local(state->buf, state->sender); 452 rec_fprintf(state->cleanup, REC_TYPE_NORM, 453 "\t(envelope-from <%s>)", STR(state->buf)); 454#endif 455 456 /* 457 * Write the message content. 458 * 459 * XXX Force an empty record when the queue file content begins with 460 * whitespace, so that it won't be considered as being part of our own 461 * Received: header. What an ugly Kluge. 462 * 463 * XXX Deal with UNIX-style From_ lines at the start of message content just 464 * in case. 465 */ 466 for (next = STR(state->message); /* void */ ; /* void */ ) { 467 if ((ch = qmqpd_next_line(state->message, &start, &len, &next)) < 0) 468 break; 469 if (ch == '\n') 470 rec_type = REC_TYPE_NORM; 471 else 472 rec_type = REC_TYPE_CONT; 473 if (first) { 474 if (strncmp(start + strspn(start, ">"), "From ", 5) == 0) { 475 rec_fprintf(state->cleanup, rec_type, 476 "X-Mailbox-Line: %.*s", len, start); 477 continue; 478 } 479 first = 0; 480 if (len > 0 && IS_SPACE_TAB(start[0])) 481 rec_put(state->cleanup, REC_TYPE_NORM, "", 0); 482 } 483 if (rec_put(state->cleanup, rec_type, start, len) < 0) { 484 state->err = CLEANUP_STAT_WRITE; 485 return; 486 } 487 } 488} 489 490/* qmqpd_close_file - close queue file */ 491 492static void qmqpd_close_file(QMQPD_STATE *state) 493{ 494 495 /* 496 * Send the end-of-segment markers. 497 */ 498 if (state->err == CLEANUP_STAT_OK) 499 if (rec_fputs(state->cleanup, REC_TYPE_XTRA, "") < 0 500 || rec_fputs(state->cleanup, REC_TYPE_END, "") < 0 501 || vstream_fflush(state->cleanup)) 502 state->err = CLEANUP_STAT_WRITE; 503 504 /* 505 * Finish the queue file or finish the cleanup conversation. 506 */ 507 if (state->err == 0) 508 state->err = mail_stream_finish(state->dest, state->why_rejected); 509 else 510 mail_stream_cleanup(state->dest); 511 state->dest = 0; 512} 513 514/* qmqpd_reply - send status to client and optionally log message */ 515 516static void qmqpd_reply(QMQPD_STATE *state, int log_message, 517 int status_code, const char *fmt,...) 518{ 519 va_list ap; 520 521 /* 522 * Optionally change hard errors into retryable ones. Send the reply and 523 * optionally log it. Always insert a delay before reporting a problem. 524 * This slows down software run-away conditions. 525 */ 526 if (status_code == QMQPD_STAT_HARD && var_soft_bounce) 527 status_code = QMQPD_STAT_RETRY; 528 VSTRING_RESET(state->buf); 529 VSTRING_ADDCH(state->buf, status_code); 530 va_start(ap, fmt); 531 vstring_vsprintf_append(state->buf, fmt, ap); 532 va_end(ap); 533 NETSTRING_PUT_BUF(state->client, state->buf); 534 if (log_message) 535 (status_code == QMQPD_STAT_OK ? msg_info : msg_warn) ("%s: %s: %s", 536 state->queue_id, state->namaddr, STR(state->buf) + 1); 537 if (status_code != QMQPD_STAT_OK) 538 sleep(var_qmqpd_err_sleep); 539 netstring_fflush(state->client); 540} 541 542/* qmqpd_send_status - send mail transaction completion status */ 543 544static void qmqpd_send_status(QMQPD_STATE *state) 545{ 546 547 /* 548 * One message may suffer from multiple errors, so complain only about 549 * the most severe error. 550 * 551 * See also: smtpd.c 552 */ 553 state->where = "sending completion status"; 554 555 if (state->err == CLEANUP_STAT_OK) { 556 qmqpd_reply(state, DONT_LOG, QMQPD_STAT_OK, 557 "Ok: queued as %s", state->queue_id); 558 } else if ((state->err & CLEANUP_STAT_DEFER) != 0) { 559 qmqpd_reply(state, DO_LOG, QMQPD_STAT_RETRY, 560 "Error: %s", STR(state->why_rejected)); 561 } else if ((state->err & CLEANUP_STAT_BAD) != 0) { 562 qmqpd_reply(state, DO_LOG, QMQPD_STAT_RETRY, 563 "Error: internal error %d", state->err); 564 } else if ((state->err & CLEANUP_STAT_SIZE) != 0) { 565 qmqpd_reply(state, DO_LOG, QMQPD_STAT_HARD, 566 "Error: message too large"); 567 } else if ((state->err & CLEANUP_STAT_HOPS) != 0) { 568 qmqpd_reply(state, DO_LOG, QMQPD_STAT_HARD, 569 "Error: too many hops"); 570 } else if ((state->err & CLEANUP_STAT_CONT) != 0) { 571 qmqpd_reply(state, DO_LOG, STR(state->why_rejected)[0] == '4' ? 572 QMQPD_STAT_RETRY : QMQPD_STAT_HARD, 573 "Error: %s", STR(state->why_rejected)); 574 } else if ((state->err & CLEANUP_STAT_WRITE) != 0) { 575 qmqpd_reply(state, DO_LOG, QMQPD_STAT_RETRY, 576 "Error: queue file write error"); 577 } else if ((state->err & CLEANUP_STAT_RCPT) != 0) { 578 qmqpd_reply(state, DO_LOG, QMQPD_STAT_HARD, 579 "Error: no recipients specified"); 580 } else { 581 qmqpd_reply(state, DO_LOG, QMQPD_STAT_RETRY, 582 "Error: internal error %d", state->err); 583 } 584} 585 586/* qmqpd_receive - receive QMQP message+sender+recipients */ 587 588static void qmqpd_receive(QMQPD_STATE *state) 589{ 590 591 /* 592 * Open a queue file. This must be first so that we can simplify the 593 * error logging and always include the queue ID information. 594 */ 595 qmqpd_open_file(state); 596 597 /* 598 * Read and ignore the over-all netstring length indicator. 599 */ 600 state->where = "receiving QMQP packet header"; 601 (void) netstring_get_length(state->client); 602 603 /* 604 * XXX Read the message content into memory, because Postfix expects to 605 * store the sender before storing the message content. Fixing that 606 * requires changes to pickup, cleanup, qmgr, and perhaps elsewhere, so 607 * that will have to happen later when I have more time. However, QMQP is 608 * used for mailing list distribution, so the bulk of the volume is 609 * expected to be not message content but recipients, and recipients are 610 * not accumulated in memory. 611 */ 612 qmqpd_read_content(state); 613 614 /* 615 * Read and write the envelope sender. 616 */ 617 qmqpd_copy_sender(state); 618 619 /* 620 * Record some session attributes. 621 */ 622 qmqpd_write_attributes(state); 623 624 /* 625 * Read and write the envelope recipients, including the optional big 626 * brother recipient. 627 */ 628 qmqpd_copy_recipients(state); 629 630 /* 631 * Start the message content segment, prepend our own Received: header, 632 * and write the message content. 633 */ 634 if (state->err == 0) 635 qmqpd_write_content(state); 636 637 /* 638 * Close the queue file. 639 */ 640 qmqpd_close_file(state); 641 642 /* 643 * Report the completion status to the client. 644 */ 645 qmqpd_send_status(state); 646} 647 648/* qmqpd_proto - speak the QMQP "protocol" */ 649 650static void qmqpd_proto(QMQPD_STATE *state) 651{ 652 int status; 653 654 netstring_setup(state->client, var_qmqpd_timeout); 655 656 switch (status = vstream_setjmp(state->client)) { 657 658 default: 659 msg_panic("qmqpd_proto: unknown status %d", status); 660 661 case NETSTRING_ERR_EOF: 662 state->reason = "lost connection"; 663 break; 664 665 case NETSTRING_ERR_TIME: 666 state->reason = "read/write timeout"; 667 break; 668 669 case NETSTRING_ERR_FORMAT: 670 state->reason = "netstring format error"; 671 if (vstream_setjmp(state->client) == 0) 672 if (state->reason && state->where) 673 qmqpd_reply(state, DONT_LOG, QMQPD_STAT_HARD, "%s while %s", 674 state->reason, state->where); 675 break; 676 677 case NETSTRING_ERR_SIZE: 678 state->reason = "netstring length exceeds storage limit"; 679 if (vstream_setjmp(state->client) == 0) 680 if (state->reason && state->where) 681 qmqpd_reply(state, DONT_LOG, QMQPD_STAT_HARD, "%s while %s", 682 state->reason, state->where); 683 break; 684 685 case 0: 686 687 /* 688 * See if we want to talk to this client at all. 689 */ 690 if (namadr_list_match(qmqpd_clients, state->name, state->addr) != 0) { 691 qmqpd_receive(state); 692 } else if (qmqpd_clients->error == 0) { 693 qmqpd_reply(state, DONT_LOG, QMQPD_STAT_HARD, 694 "Error: %s is not authorized to use this service", 695 state->namaddr); 696 } else { 697 qmqpd_reply(state, DONT_LOG, QMQPD_STAT_RETRY, 698 "Error: server configuration error"); 699 } 700 break; 701 } 702 703 /* 704 * Log abnormal session termination. Indicate the last recognized state 705 * before things went wrong. 706 */ 707 if (state->reason && state->where) 708 msg_info("%s: %s: %s while %s", 709 state->queue_id, state->namaddr, state->reason, state->where); 710} 711 712/* qmqpd_service - service one client */ 713 714static void qmqpd_service(VSTREAM *stream, char *unused_service, char **argv) 715{ 716 QMQPD_STATE *state; 717 718 /* 719 * Sanity check. This service takes no command-line arguments. 720 */ 721 if (argv[0]) 722 msg_fatal("unexpected command-line argument: %s", argv[0]); 723 724 /* 725 * For sanity, require that at least one of INET or INET6 is enabled. 726 * Otherwise, we can't look up interface information, and we can't 727 * convert names or addresses. 728 */ 729 if (inet_proto_info()->ai_family_list[0] == 0) 730 msg_fatal("all network protocols are disabled (%s = %s)", 731 VAR_INET_PROTOCOLS, var_inet_protocols); 732 733 /* 734 * This routine runs when a client has connected to our network port. 735 * Look up and sanitize the peer name and initialize some connection- 736 * specific state. 737 */ 738 state = qmqpd_state_alloc(stream); 739 740 /* 741 * See if we need to turn on verbose logging for this client. 742 */ 743 debug_peer_check(state->name, state->addr); 744 745 /* 746 * Provide the QMQP service. 747 */ 748 msg_info("connect from %s", state->namaddr); 749 qmqpd_proto(state); 750 msg_info("disconnect from %s", state->namaddr); 751 752 /* 753 * After the client has gone away, clean up whatever we have set up at 754 * connection time. 755 */ 756 debug_peer_restore(); 757 qmqpd_state_free(state); 758} 759 760/* pre_accept - see if tables have changed */ 761 762static void pre_accept(char *unused_name, char **unused_argv) 763{ 764 const char *table; 765 766 if ((table = dict_changed_name()) != 0) { 767 msg_info("table %s has changed -- restarting", table); 768 exit(0); 769 } 770} 771 772/* pre_jail_init - pre-jail initialization */ 773 774static void pre_jail_init(char *unused_name, char **unused_argv) 775{ 776 debug_peer_init(); 777 qmqpd_clients = 778 namadr_list_init(MATCH_FLAG_RETURN 779 | match_parent_style(VAR_QMQPD_CLIENTS), 780 var_qmqpd_clients); 781} 782 783/* post_jail_init - post-jail initialization */ 784 785static void post_jail_init(char *unused_name, char **unused_argv) 786{ 787 788 /* 789 * Initialize the receive transparency options: do we want unknown 790 * recipient checks, do we want address mapping. 791 */ 792 qmqpd_input_transp_mask = 793 input_transp_mask(VAR_INPUT_TRANSP, var_input_transp); 794} 795 796MAIL_VERSION_STAMP_DECLARE; 797 798/* main - the main program */ 799 800int main(int argc, char **argv) 801{ 802 static const CONFIG_TIME_TABLE time_table[] = { 803 VAR_QMTPD_TMOUT, DEF_QMTPD_TMOUT, &var_qmqpd_timeout, 1, 0, 804 VAR_QMTPD_ERR_SLEEP, DEF_QMTPD_ERR_SLEEP, &var_qmqpd_err_sleep, 0, 0, 805 0, 806 }; 807 static const CONFIG_STR_TABLE str_table[] = { 808 VAR_FILTER_XPORT, DEF_FILTER_XPORT, &var_filter_xport, 0, 0, 809 VAR_QMQPD_CLIENTS, DEF_QMQPD_CLIENTS, &var_qmqpd_clients, 0, 0, 810 VAR_INPUT_TRANSP, DEF_INPUT_TRANSP, &var_input_transp, 0, 0, 811 0, 812 }; 813 static const CONFIG_BOOL_TABLE bool_table[] = { 814 VAR_QMQPD_CLIENT_PORT_LOG, DEF_QMQPD_CLIENT_PORT_LOG, &var_qmqpd_client_port_log, 815 0, 816 }; 817 818 /* 819 * Fingerprint executables and core dumps. 820 */ 821 MAIL_VERSION_STAMP_ALLOCATE; 822 823 /* 824 * Pass control to the single-threaded service skeleton. 825 */ 826 single_server_main(argc, argv, qmqpd_service, 827 MAIL_SERVER_TIME_TABLE, time_table, 828 MAIL_SERVER_STR_TABLE, str_table, 829 MAIL_SERVER_BOOL_TABLE, bool_table, 830 MAIL_SERVER_PRE_INIT, pre_jail_init, 831 MAIL_SERVER_PRE_ACCEPT, pre_accept, 832 MAIL_SERVER_POST_INIT, post_jail_init, 833 0); 834} 835