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