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