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