xref: /netbsd-src/external/ibm-public/postfix/dist/src/qmqpd/qmqpd.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
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