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