xref: /openbsd/usr.sbin/smtpd/queue.c (revision 510586ac)
1 /*	$OpenBSD: queue.c,v 1.196 2024/01/20 09:01:03 claudio Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
5  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
6  * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <inttypes.h>
22 #include <pwd.h>
23 #include <signal.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <unistd.h>
28 
29 #include "smtpd.h"
30 #include "log.h"
31 
32 static void queue_imsg(struct mproc *, struct imsg *);
33 static void queue_timeout(int, short, void *);
34 static void queue_bounce(struct envelope *, struct delivery_bounce *);
35 static void queue_shutdown(void);
36 static void queue_log(const struct envelope *, const char *, const char *);
37 static void queue_msgid_walk(int, short, void *);
38 
39 
40 static void
queue_imsg(struct mproc * p,struct imsg * imsg)41 queue_imsg(struct mproc *p, struct imsg *imsg)
42 {
43 	struct delivery_bounce	 bounce;
44 	struct msg_walkinfo	*wi;
45 	struct timeval		 tv;
46 	struct bounce_req_msg	*req_bounce;
47 	struct envelope		 evp;
48 	struct msg		 m;
49 	const char		*reason;
50 	uint64_t		 reqid, evpid, holdq;
51 	uint32_t		 msgid;
52 	time_t			 nexttry;
53 	size_t			 n_evp;
54 	int			 fd, mta_ext, ret, v, flags, code;
55 
56 	if (imsg == NULL)
57 		queue_shutdown();
58 
59 	memset(&bounce, 0, sizeof(struct delivery_bounce));
60 
61 	switch (imsg->hdr.type) {
62 	case IMSG_SMTP_MESSAGE_CREATE:
63 		m_msg(&m, imsg);
64 		m_get_id(&m, &reqid);
65 		m_end(&m);
66 
67 		ret = queue_message_create(&msgid);
68 
69 		m_create(p, IMSG_SMTP_MESSAGE_CREATE, 0, 0, -1);
70 		m_add_id(p, reqid);
71 		if (ret == 0)
72 			m_add_int(p, 0);
73 		else {
74 			m_add_int(p, 1);
75 			m_add_msgid(p, msgid);
76 		}
77 		m_close(p);
78 		return;
79 
80 	case IMSG_SMTP_MESSAGE_ROLLBACK:
81 		m_msg(&m, imsg);
82 		m_get_msgid(&m, &msgid);
83 		m_end(&m);
84 
85 		queue_message_delete(msgid);
86 
87 		m_create(p_scheduler, IMSG_QUEUE_MESSAGE_ROLLBACK,
88 		    0, 0, -1);
89 		m_add_msgid(p_scheduler, msgid);
90 		m_close(p_scheduler);
91 		return;
92 
93 	case IMSG_SMTP_MESSAGE_COMMIT:
94 		m_msg(&m, imsg);
95 		m_get_id(&m, &reqid);
96 		m_get_msgid(&m, &msgid);
97 		m_end(&m);
98 
99 		ret = queue_message_commit(msgid);
100 
101 		m_create(p, IMSG_SMTP_MESSAGE_COMMIT, 0, 0, -1);
102 		m_add_id(p, reqid);
103 		m_add_int(p, (ret == 0) ? 0 : 1);
104 		m_close(p);
105 
106 		if (ret) {
107 			m_create(p_scheduler, IMSG_QUEUE_MESSAGE_COMMIT,
108 			    0, 0, -1);
109 			m_add_msgid(p_scheduler, msgid);
110 			m_close(p_scheduler);
111 		}
112 		return;
113 
114 	case IMSG_SMTP_MESSAGE_OPEN:
115 		m_msg(&m, imsg);
116 		m_get_id(&m, &reqid);
117 		m_get_msgid(&m, &msgid);
118 		m_end(&m);
119 
120 		fd = queue_message_fd_rw(msgid);
121 
122 		m_create(p, IMSG_SMTP_MESSAGE_OPEN, 0, 0, fd);
123 		m_add_id(p, reqid);
124 		m_add_int(p, (fd == -1) ? 0 : 1);
125 		m_close(p);
126 		return;
127 
128 	case IMSG_QUEUE_SMTP_SESSION:
129 		bounce_fd(imsg_get_fd(imsg));
130 		return;
131 
132 	case IMSG_LKA_ENVELOPE_SUBMIT:
133 		m_msg(&m, imsg);
134 		m_get_id(&m, &reqid);
135 		m_get_envelope(&m, &evp);
136 		m_end(&m);
137 
138 		if (evp.id == 0)
139 			log_warnx("warn: imsg_queue_submit_envelope: evpid=0");
140 		if (evpid_to_msgid(evp.id) == 0)
141 			log_warnx("warn: imsg_queue_submit_envelope: msgid=0, "
142 			    "evpid=%016"PRIx64, evp.id);
143 		ret = queue_envelope_create(&evp);
144 		m_create(p_dispatcher, IMSG_QUEUE_ENVELOPE_SUBMIT, 0, 0, -1);
145 		m_add_id(p_dispatcher, reqid);
146 		if (ret == 0)
147 			m_add_int(p_dispatcher, 0);
148 		else {
149 			m_add_int(p_dispatcher, 1);
150 			m_add_evpid(p_dispatcher, evp.id);
151 		}
152 		m_close(p_dispatcher);
153 		if (ret) {
154 			m_create(p_scheduler,
155 			    IMSG_QUEUE_ENVELOPE_SUBMIT, 0, 0, -1);
156 			m_add_envelope(p_scheduler, &evp);
157 			m_close(p_scheduler);
158 		}
159 		return;
160 
161 	case IMSG_LKA_ENVELOPE_COMMIT:
162 		m_msg(&m, imsg);
163 		m_get_id(&m, &reqid);
164 		m_end(&m);
165 		m_create(p_dispatcher, IMSG_QUEUE_ENVELOPE_COMMIT, 0, 0, -1);
166 		m_add_id(p_dispatcher, reqid);
167 		m_add_int(p_dispatcher, 1);
168 		m_close(p_dispatcher);
169 		return;
170 
171 	case IMSG_SCHED_ENVELOPE_REMOVE:
172 		m_msg(&m, imsg);
173 		m_get_evpid(&m, &evpid);
174 		m_end(&m);
175 
176 		m_create(p_scheduler, IMSG_QUEUE_ENVELOPE_ACK, 0, 0, -1);
177 		m_add_evpid(p_scheduler, evpid);
178 		m_close(p_scheduler);
179 
180 		/* already removed by scheduler */
181 		if (queue_envelope_load(evpid, &evp) == 0)
182 			return;
183 
184 		queue_log(&evp, "Remove", "Removed by administrator");
185 		queue_envelope_delete(evpid);
186 		return;
187 
188 	case IMSG_SCHED_ENVELOPE_EXPIRE:
189 		m_msg(&m, imsg);
190 		m_get_evpid(&m, &evpid);
191 		m_end(&m);
192 
193 		m_create(p_scheduler, IMSG_QUEUE_ENVELOPE_ACK, 0, 0, -1);
194 		m_add_evpid(p_scheduler, evpid);
195 		m_close(p_scheduler);
196 
197 		/* already removed by scheduler*/
198 		if (queue_envelope_load(evpid, &evp) == 0)
199 			return;
200 
201 		bounce.type = B_FAILED;
202 		envelope_set_errormsg(&evp, "Envelope expired");
203 		envelope_set_esc_class(&evp, ESC_STATUS_PERMFAIL);
204 		envelope_set_esc_code(&evp, ESC_DELIVERY_TIME_EXPIRED);
205 		queue_bounce(&evp, &bounce);
206 		queue_log(&evp, "Expire", "Envelope expired");
207 		queue_envelope_delete(evpid);
208 		return;
209 
210 	case IMSG_SCHED_ENVELOPE_BOUNCE:
211 		CHECK_IMSG_DATA_SIZE(imsg, sizeof *req_bounce);
212 		req_bounce = imsg->data;
213 		evpid = req_bounce->evpid;
214 
215 		if (queue_envelope_load(evpid, &evp) == 0) {
216 			log_warnx("queue: bounce: failed to load envelope");
217 			m_create(p_scheduler, IMSG_QUEUE_ENVELOPE_REMOVE, 0, 0, -1);
218 			m_add_evpid(p_scheduler, evpid);
219 			m_add_u32(p_scheduler, 0); /* not in-flight */
220 			m_close(p_scheduler);
221 			return;
222 		}
223 		queue_bounce(&evp, &req_bounce->bounce);
224 		evp.lastbounce = req_bounce->timestamp;
225 		if (!queue_envelope_update(&evp))
226 			log_warnx("warn: could not update envelope %016"PRIx64, evpid);
227 		return;
228 
229 	case IMSG_SCHED_ENVELOPE_DELIVER:
230 		m_msg(&m, imsg);
231 		m_get_evpid(&m, &evpid);
232 		m_end(&m);
233 		if (queue_envelope_load(evpid, &evp) == 0) {
234 			log_warnx("queue: deliver: failed to load envelope");
235 			m_create(p_scheduler, IMSG_QUEUE_ENVELOPE_REMOVE, 0, 0, -1);
236 			m_add_evpid(p_scheduler, evpid);
237 			m_add_u32(p_scheduler, 1); /* in-flight */
238 			m_close(p_scheduler);
239 			return;
240 		}
241 		evp.lasttry = time(NULL);
242 		m_create(p_dispatcher, IMSG_QUEUE_DELIVER, 0, 0, -1);
243 		m_add_envelope(p_dispatcher, &evp);
244 		m_close(p_dispatcher);
245 		return;
246 
247 	case IMSG_SCHED_ENVELOPE_INJECT:
248 		m_msg(&m, imsg);
249 		m_get_evpid(&m, &evpid);
250 		m_end(&m);
251 		bounce_add(evpid);
252 		return;
253 
254 	case IMSG_SCHED_ENVELOPE_TRANSFER:
255 		m_msg(&m, imsg);
256 		m_get_evpid(&m, &evpid);
257 		m_end(&m);
258 		if (queue_envelope_load(evpid, &evp) == 0) {
259 			log_warnx("queue: failed to load envelope");
260 			m_create(p_scheduler, IMSG_QUEUE_ENVELOPE_REMOVE, 0, 0, -1);
261 			m_add_evpid(p_scheduler, evpid);
262 			m_add_u32(p_scheduler, 1); /* in-flight */
263 			m_close(p_scheduler);
264 			return;
265 		}
266 		evp.lasttry = time(NULL);
267 		m_create(p_dispatcher, IMSG_QUEUE_TRANSFER, 0, 0, -1);
268 		m_add_envelope(p_dispatcher, &evp);
269 		m_close(p_dispatcher);
270 		return;
271 
272 	case IMSG_CTL_LIST_ENVELOPES:
273 		if (imsg->hdr.len == sizeof imsg->hdr) {
274 			m_forward(p_control, imsg);
275 			return;
276 		}
277 
278 		m_msg(&m, imsg);
279 		m_get_evpid(&m, &evpid);
280 		m_get_int(&m, &flags);
281 		m_get_time(&m, &nexttry);
282 		m_end(&m);
283 
284 		if (queue_envelope_load(evpid, &evp) == 0)
285 			return; /* Envelope is gone, drop it */
286 
287 		/*
288 		 * XXX consistency: The envelope might already be on
289 		 * its way back to the scheduler.  We need to detect
290 		 * this properly and report that state.
291 		 */
292 		if (flags & EF_INFLIGHT) {
293 			/*
294 			 * Not exactly correct but pretty close: The
295 			 * value is not recorded on the envelope unless
296 			 * a tempfail occurs.
297 			 */
298 			evp.lasttry = nexttry;
299 		}
300 
301 		m_create(p_control, IMSG_CTL_LIST_ENVELOPES,
302 		    imsg->hdr.peerid, 0, -1);
303 		m_add_int(p_control, flags);
304 		m_add_time(p_control, nexttry);
305 		m_add_envelope(p_control, &evp);
306 		m_close(p_control);
307 		return;
308 
309 	case IMSG_MDA_OPEN_MESSAGE:
310 	case IMSG_MTA_OPEN_MESSAGE:
311 		m_msg(&m, imsg);
312 		m_get_id(&m, &reqid);
313 		m_get_msgid(&m, &msgid);
314 		m_end(&m);
315 		fd = queue_message_fd_r(msgid);
316 		m_create(p, imsg->hdr.type, 0, 0, fd);
317 		m_add_id(p, reqid);
318 		m_close(p);
319 		return;
320 
321 	case IMSG_MDA_DELIVERY_OK:
322 	case IMSG_MTA_DELIVERY_OK:
323 		m_msg(&m, imsg);
324 		m_get_evpid(&m, &evpid);
325 		if (imsg->hdr.type == IMSG_MTA_DELIVERY_OK)
326 			m_get_int(&m, &mta_ext);
327 		m_end(&m);
328 		if (queue_envelope_load(evpid, &evp) == 0) {
329 			log_warn("queue: dsn: failed to load envelope");
330 			return;
331 		}
332 		if (evp.dsn_notify & DSN_SUCCESS) {
333 			bounce.type = B_DELIVERED;
334 			bounce.dsn_ret = evp.dsn_ret;
335 			envelope_set_esc_class(&evp, ESC_STATUS_OK);
336 			if (imsg->hdr.type == IMSG_MDA_DELIVERY_OK)
337 				queue_bounce(&evp, &bounce);
338 			else if (imsg->hdr.type == IMSG_MTA_DELIVERY_OK &&
339 			    (mta_ext & MTA_EXT_DSN) == 0) {
340 				bounce.mta_without_dsn = 1;
341 				queue_bounce(&evp, &bounce);
342 			}
343 		}
344 		queue_envelope_delete(evpid);
345 		m_create(p_scheduler, IMSG_QUEUE_DELIVERY_OK, 0, 0, -1);
346 		m_add_evpid(p_scheduler, evpid);
347 		m_close(p_scheduler);
348 		return;
349 
350 	case IMSG_MDA_DELIVERY_TEMPFAIL:
351 	case IMSG_MTA_DELIVERY_TEMPFAIL:
352 		m_msg(&m, imsg);
353 		m_get_evpid(&m, &evpid);
354 		m_get_string(&m, &reason);
355 		m_get_int(&m, &code);
356 		m_end(&m);
357 		if (queue_envelope_load(evpid, &evp) == 0) {
358 			log_warnx("queue: tempfail: failed to load envelope");
359 			m_create(p_scheduler, IMSG_QUEUE_ENVELOPE_REMOVE, 0, 0, -1);
360 			m_add_evpid(p_scheduler, evpid);
361 			m_add_u32(p_scheduler, 1); /* in-flight */
362 			m_close(p_scheduler);
363 			return;
364 		}
365 		envelope_set_errormsg(&evp, "%s", reason);
366 		envelope_set_esc_class(&evp, ESC_STATUS_TEMPFAIL);
367 		envelope_set_esc_code(&evp, code);
368 		evp.retry++;
369 		if (!queue_envelope_update(&evp))
370 			log_warnx("warn: could not update envelope %016"PRIx64, evpid);
371 		m_create(p_scheduler, IMSG_QUEUE_DELIVERY_TEMPFAIL, 0, 0, -1);
372 		m_add_envelope(p_scheduler, &evp);
373 		m_close(p_scheduler);
374 		return;
375 
376 	case IMSG_MDA_DELIVERY_PERMFAIL:
377 	case IMSG_MTA_DELIVERY_PERMFAIL:
378 		m_msg(&m, imsg);
379 		m_get_evpid(&m, &evpid);
380 		m_get_string(&m, &reason);
381 		m_get_int(&m, &code);
382 		m_end(&m);
383 		if (queue_envelope_load(evpid, &evp) == 0) {
384 			log_warnx("queue: permfail: failed to load envelope");
385 			m_create(p_scheduler, IMSG_QUEUE_ENVELOPE_REMOVE, 0, 0, -1);
386 			m_add_evpid(p_scheduler, evpid);
387 			m_add_u32(p_scheduler, 1); /* in-flight */
388 			m_close(p_scheduler);
389 			return;
390 		}
391 		bounce.type = B_FAILED;
392 		envelope_set_errormsg(&evp, "%s", reason);
393 		envelope_set_esc_class(&evp, ESC_STATUS_PERMFAIL);
394 		envelope_set_esc_code(&evp, code);
395 		queue_bounce(&evp, &bounce);
396 		queue_envelope_delete(evpid);
397 		m_create(p_scheduler, IMSG_QUEUE_DELIVERY_PERMFAIL, 0, 0, -1);
398 		m_add_evpid(p_scheduler, evpid);
399 		m_close(p_scheduler);
400 		return;
401 
402 	case IMSG_MDA_DELIVERY_LOOP:
403 	case IMSG_MTA_DELIVERY_LOOP:
404 		m_msg(&m, imsg);
405 		m_get_evpid(&m, &evpid);
406 		m_end(&m);
407 		if (queue_envelope_load(evpid, &evp) == 0) {
408 			log_warnx("queue: loop: failed to load envelope");
409 			m_create(p_scheduler, IMSG_QUEUE_ENVELOPE_REMOVE, 0, 0, -1);
410 			m_add_evpid(p_scheduler, evpid);
411 			m_add_u32(p_scheduler, 1); /* in-flight */
412 			m_close(p_scheduler);
413 			return;
414 		}
415 		envelope_set_errormsg(&evp, "%s", "Loop detected");
416 		envelope_set_esc_class(&evp, ESC_STATUS_TEMPFAIL);
417 		envelope_set_esc_code(&evp, ESC_ROUTING_LOOP_DETECTED);
418 		bounce.type = B_FAILED;
419 		queue_bounce(&evp, &bounce);
420 		queue_envelope_delete(evp.id);
421 		m_create(p_scheduler, IMSG_QUEUE_DELIVERY_LOOP, 0, 0, -1);
422 		m_add_evpid(p_scheduler, evp.id);
423 		m_close(p_scheduler);
424 		return;
425 
426 	case IMSG_MTA_DELIVERY_HOLD:
427 	case IMSG_MDA_DELIVERY_HOLD:
428 		imsg->hdr.type = IMSG_QUEUE_HOLDQ_HOLD;
429 		m_forward(p_scheduler, imsg);
430 		return;
431 
432 	case IMSG_MTA_SCHEDULE:
433 		imsg->hdr.type = IMSG_QUEUE_ENVELOPE_SCHEDULE;
434 		m_forward(p_scheduler, imsg);
435 		return;
436 
437 	case IMSG_MTA_HOLDQ_RELEASE:
438 	case IMSG_MDA_HOLDQ_RELEASE:
439 		m_msg(&m, imsg);
440 		m_get_id(&m, &holdq);
441 		m_get_int(&m, &v);
442 		m_end(&m);
443 		m_create(p_scheduler, IMSG_QUEUE_HOLDQ_RELEASE, 0, 0, -1);
444 		if (imsg->hdr.type == IMSG_MTA_HOLDQ_RELEASE)
445 			m_add_int(p_scheduler, D_MTA);
446 		else
447 			m_add_int(p_scheduler, D_MDA);
448 		m_add_id(p_scheduler, holdq);
449 		m_add_int(p_scheduler, v);
450 		m_close(p_scheduler);
451 		return;
452 
453 	case IMSG_CTL_PAUSE_MDA:
454 	case IMSG_CTL_PAUSE_MTA:
455 	case IMSG_CTL_RESUME_MDA:
456 	case IMSG_CTL_RESUME_MTA:
457 		m_forward(p_scheduler, imsg);
458 		return;
459 
460 	case IMSG_CTL_VERBOSE:
461 		m_msg(&m, imsg);
462 		m_get_int(&m, &v);
463 		m_end(&m);
464 		log_trace_verbose(v);
465 		return;
466 
467 	case IMSG_CTL_PROFILE:
468 		m_msg(&m, imsg);
469 		m_get_int(&m, &v);
470 		m_end(&m);
471 		profiling = v;
472 		return;
473 
474 	case IMSG_CTL_DISCOVER_EVPID:
475 		m_msg(&m, imsg);
476 		m_get_evpid(&m, &evpid);
477 		m_end(&m);
478 		if (queue_envelope_load(evpid, &evp) == 0) {
479 			log_warnx("queue: discover: failed to load "
480 			    "envelope %016" PRIx64, evpid);
481 			n_evp = 0;
482 			m_compose(p_control, imsg->hdr.type,
483 			    imsg->hdr.peerid, 0, -1,
484 			    &n_evp, sizeof n_evp);
485 			return;
486 		}
487 
488 		m_create(p_scheduler, IMSG_QUEUE_DISCOVER_EVPID,
489 		    0, 0, -1);
490 		m_add_envelope(p_scheduler, &evp);
491 		m_close(p_scheduler);
492 
493 		m_create(p_scheduler, IMSG_QUEUE_DISCOVER_MSGID,
494 		    0, 0, -1);
495 		m_add_msgid(p_scheduler, evpid_to_msgid(evpid));
496 		m_close(p_scheduler);
497 		n_evp = 1;
498 		m_compose(p_control, imsg->hdr.type, imsg->hdr.peerid,
499 		    0, -1, &n_evp, sizeof n_evp);
500 		return;
501 
502 	case IMSG_CTL_DISCOVER_MSGID:
503 		m_msg(&m, imsg);
504 		m_get_msgid(&m, &msgid);
505 		m_end(&m);
506 		/* handle concurrent walk requests */
507 		wi = xcalloc(1, sizeof *wi);
508 		wi->msgid = msgid;
509 		wi->peerid = imsg->hdr.peerid;
510 		evtimer_set(&wi->ev, queue_msgid_walk, wi);
511 		tv.tv_sec = 0;
512 		tv.tv_usec = 10;
513 		evtimer_add(&wi->ev, &tv);
514 		return;
515 	}
516 
517 	fatalx("queue_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type));
518 }
519 
520 static void
queue_msgid_walk(int fd,short event,void * arg)521 queue_msgid_walk(int fd, short event, void *arg)
522 {
523 	struct envelope		 evp;
524 	struct timeval		 tv;
525 	struct msg_walkinfo	*wi = arg;
526 	int			 r;
527 
528 	r = queue_message_walk(&evp, wi->msgid, &wi->done, &wi->data);
529 	if (r == -1) {
530 		if (wi->n_evp) {
531 			m_create(p_scheduler, IMSG_QUEUE_DISCOVER_MSGID,
532 			    0, 0, -1);
533 			m_add_msgid(p_scheduler, wi->msgid);
534 			m_close(p_scheduler);
535 		}
536 
537 		m_compose(p_control, IMSG_CTL_DISCOVER_MSGID, wi->peerid, 0, -1,
538 		    &wi->n_evp, sizeof wi->n_evp);
539 		evtimer_del(&wi->ev);
540 		free(wi);
541 		return;
542 	}
543 
544 	if (r) {
545 		m_create(p_scheduler, IMSG_QUEUE_DISCOVER_EVPID, 0, 0, -1);
546 		m_add_envelope(p_scheduler, &evp);
547 		m_close(p_scheduler);
548 		wi->n_evp += 1;
549 	}
550 
551 	tv.tv_sec = 0;
552 	tv.tv_usec = 10;
553 	evtimer_set(&wi->ev, queue_msgid_walk, wi);
554 	evtimer_add(&wi->ev, &tv);
555 }
556 
557 static void
queue_bounce(struct envelope * e,struct delivery_bounce * d)558 queue_bounce(struct envelope *e, struct delivery_bounce *d)
559 {
560 	struct envelope	b;
561 
562 	b = *e;
563 	b.type = D_BOUNCE;
564 	b.agent.bounce = *d;
565 	b.retry = 0;
566 	b.lasttry = 0;
567 	b.creation = time(NULL);
568 	b.ttl = 3600 * 24 * 7;
569 
570 	if (e->dsn_notify & DSN_NEVER)
571 		return;
572 
573 	if (b.id == 0)
574 		log_warnx("warn: queue_bounce: evpid=0");
575 	if (evpid_to_msgid(b.id) == 0)
576 		log_warnx("warn: queue_bounce: msgid=0, evpid=%016"PRIx64,
577 			b.id);
578 	if (e->type == D_BOUNCE) {
579 		log_warnx("warn: queue: double bounce!");
580 	} else if (e->sender.user[0] == '\0') {
581 		log_warnx("warn: queue: no return path!");
582 	} else if (!queue_envelope_create(&b)) {
583 		log_warnx("warn: queue: cannot bounce!");
584 	} else {
585 		log_debug("debug: queue: bouncing evp:%016" PRIx64
586 		    " as evp:%016" PRIx64, e->id, b.id);
587 
588 		m_create(p_scheduler, IMSG_QUEUE_ENVELOPE_SUBMIT, 0, 0, -1);
589 		m_add_envelope(p_scheduler, &b);
590 		m_close(p_scheduler);
591 
592 		m_create(p_scheduler, IMSG_QUEUE_MESSAGE_COMMIT, 0, 0, -1);
593 		m_add_msgid(p_scheduler, evpid_to_msgid(b.id));
594 		m_close(p_scheduler);
595 
596 		stat_increment("queue.bounce", 1);
597 	}
598 }
599 
600 static void
queue_shutdown(void)601 queue_shutdown(void)
602 {
603 	log_debug("debug: queue agent exiting");
604 	queue_close();
605 	_exit(0);
606 }
607 
608 int
queue(void)609 queue(void)
610 {
611 	struct passwd	*pw;
612 	struct timeval	 tv;
613 	struct event	 ev_qload;
614 
615 	purge_config(PURGE_EVERYTHING & ~PURGE_DISPATCHERS);
616 
617 	if ((pw = getpwnam(SMTPD_QUEUE_USER)) == NULL)
618 		if ((pw = getpwnam(SMTPD_USER)) == NULL)
619 			fatalx("unknown user " SMTPD_USER);
620 
621 	env->sc_queue_flags |= QUEUE_EVPCACHE;
622 	env->sc_queue_evpcache_size = 1024;
623 
624 	if (chroot(PATH_SPOOL) == -1)
625 		fatal("queue: chroot");
626 	if (chdir("/") == -1)
627 		fatal("queue: chdir(\"/\")");
628 
629 	config_process(PROC_QUEUE);
630 
631 	if (env->sc_queue_flags & QUEUE_COMPRESSION)
632 		log_info("queue: queue compression enabled");
633 
634 	if (env->sc_queue_key) {
635 		if (!crypto_setup(env->sc_queue_key, strlen(env->sc_queue_key)))
636 			fatalx("crypto_setup: invalid key for queue encryption");
637 		log_info("queue: queue encryption enabled");
638 	}
639 
640 	if (setgroups(1, &pw->pw_gid) ||
641 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
642 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
643 		fatal("queue: cannot drop privileges");
644 
645 	imsg_callback = queue_imsg;
646 	event_init();
647 
648 	signal(SIGINT, SIG_IGN);
649 	signal(SIGTERM, SIG_IGN);
650 	signal(SIGPIPE, SIG_IGN);
651 	signal(SIGHUP, SIG_IGN);
652 
653 	config_peer(PROC_PARENT);
654 	config_peer(PROC_CONTROL);
655 	config_peer(PROC_LKA);
656 	config_peer(PROC_SCHEDULER);
657 	config_peer(PROC_DISPATCHER);
658 
659 	/* setup queue loading task */
660 	evtimer_set(&ev_qload, queue_timeout, &ev_qload);
661 	tv.tv_sec = 0;
662 	tv.tv_usec = 10;
663 	evtimer_add(&ev_qload, &tv);
664 
665 	if (pledge("stdio rpath wpath cpath flock recvfd sendfd", NULL) == -1)
666 		fatal("pledge");
667 
668 	event_dispatch();
669 	fatalx("exited event loop");
670 
671 	return (0);
672 }
673 
674 static void
queue_timeout(int fd,short event,void * p)675 queue_timeout(int fd, short event, void *p)
676 {
677 	static uint32_t	 msgid = 0;
678 	struct envelope	 evp;
679 	struct event	*ev = p;
680 	struct timeval	 tv;
681 	int		 r;
682 
683 	r = queue_envelope_walk(&evp);
684 	if (r == -1) {
685 		if (msgid) {
686 			m_create(p_scheduler, IMSG_QUEUE_MESSAGE_COMMIT,
687 			    0, 0, -1);
688 			m_add_msgid(p_scheduler, msgid);
689 			m_close(p_scheduler);
690 		}
691 		log_debug("debug: queue: done loading queue into scheduler");
692 		return;
693 	}
694 
695 	if (r) {
696 		if (msgid && evpid_to_msgid(evp.id) != msgid) {
697 			m_create(p_scheduler, IMSG_QUEUE_MESSAGE_COMMIT,
698 			    0, 0, -1);
699 			m_add_msgid(p_scheduler, msgid);
700 			m_close(p_scheduler);
701 		}
702 		msgid = evpid_to_msgid(evp.id);
703 		m_create(p_scheduler, IMSG_QUEUE_ENVELOPE_SUBMIT, 0, 0, -1);
704 		m_add_envelope(p_scheduler, &evp);
705 		m_close(p_scheduler);
706 	}
707 
708 	tv.tv_sec = 0;
709 	tv.tv_usec = 10;
710 	evtimer_add(ev, &tv);
711 }
712 
713 static void
queue_log(const struct envelope * e,const char * prefix,const char * status)714 queue_log(const struct envelope *e, const char *prefix, const char *status)
715 {
716 	char rcpt[LINE_MAX];
717 
718 	(void)strlcpy(rcpt, "-", sizeof rcpt);
719 	if (strcmp(e->rcpt.user, e->dest.user) ||
720 	    strcmp(e->rcpt.domain, e->dest.domain))
721 		(void)snprintf(rcpt, sizeof rcpt, "%s@%s",
722 		    e->rcpt.user, e->rcpt.domain);
723 
724 	log_info("%s: %s for %016" PRIx64 ": from=<%s@%s>, to=<%s@%s>, "
725 	    "rcpt=<%s>, delay=%s, stat=%s",
726 	    e->type == D_MDA ? "delivery" : "relay",
727 	    prefix,
728 	    e->id, e->sender.user, e->sender.domain,
729 	    e->dest.user, e->dest.domain,
730 	    rcpt,
731 	    duration_to_text(time(NULL) - e->creation),
732 	    status);
733 }
734