1 /* $OpenBSD: queue.c,v 1.195 2023/05/31 16:51:46 op 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 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->fd); 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 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 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 601 queue_shutdown(void) 602 { 603 log_debug("debug: queue agent exiting"); 604 queue_close(); 605 _exit(0); 606 } 607 608 int 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 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 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