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