1 /* $OpenBSD: smtpctl.c,v 1.172 2023/05/31 16:51:46 op Exp $ */ 2 3 /* 4 * Copyright (c) 2013 Eric Faurot <eric@openbsd.org> 5 * Copyright (c) 2006 Gilles Chehade <gilles@poolp.org> 6 * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> 7 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 8 * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> 9 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org> 10 * 11 * Permission to use, copy, modify, and distribute this software for any 12 * purpose with or without fee is hereby granted, provided that the above 13 * copyright notice and this permission notice appear in all copies. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24 #include <sys/un.h> 25 #include <sys/stat.h> 26 27 #include <err.h> 28 #include <errno.h> 29 #include <fts.h> 30 #include <inttypes.h> 31 #include <pwd.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <syslog.h> 35 #include <time.h> 36 #include <unistd.h> 37 #include <vis.h> 38 39 #include "smtpd.h" 40 #include "parser.h" 41 #include "log.h" 42 43 #define PATH_GZCAT "/usr/bin/gzcat" 44 #define PATH_CAT "/bin/cat" 45 #define PATH_QUEUE "/queue" 46 #define PATH_ENCRYPT "/usr/bin/encrypt" 47 48 int srv_connect(void); 49 int srv_connected(void); 50 51 void usage(void); 52 static void show_queue_envelope(struct envelope *, int); 53 static void getflag(uint *, int, char *, char *, size_t); 54 static void display(const char *); 55 static int str_to_trace(const char *); 56 static int str_to_profile(const char *); 57 static void show_offline_envelope(uint64_t); 58 static int is_gzip_fp(FILE *); 59 static int is_encrypted_fp(FILE *); 60 static int is_encrypted_buffer(const char *); 61 static int is_gzip_buffer(const char *); 62 static FILE *offline_file(void); 63 static void sendmail_compat(int, char **); 64 65 extern int spfwalk(int, struct parameter *); 66 67 extern char *__progname; 68 int sendmail; 69 struct smtpd *env; 70 struct imsgbuf *ibuf; 71 struct imsg imsg; 72 char *rdata; 73 size_t rlen; 74 time_t now; 75 76 struct queue_backend queue_backend_null; 77 struct queue_backend queue_backend_proc; 78 struct queue_backend queue_backend_ram; 79 80 __dead void 81 usage(void) 82 { 83 if (sendmail) 84 fprintf(stderr, "usage: %s [-tv] [-f from] [-F name] to ...\n", 85 __progname); 86 else 87 fprintf(stderr, "usage: %s command [argument ...]\n", 88 __progname); 89 exit(1); 90 } 91 92 void stat_increment(const char *k, size_t v) 93 { 94 } 95 96 void stat_decrement(const char *k, size_t v) 97 { 98 } 99 100 int 101 srv_connect(void) 102 { 103 struct sockaddr_un s_un; 104 int ctl_sock, saved_errno; 105 106 /* connect to smtpd control socket */ 107 if ((ctl_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) 108 err(1, "socket"); 109 110 memset(&s_un, 0, sizeof(s_un)); 111 s_un.sun_family = AF_UNIX; 112 (void)strlcpy(s_un.sun_path, SMTPD_SOCKET, sizeof(s_un.sun_path)); 113 if (connect(ctl_sock, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) { 114 saved_errno = errno; 115 close(ctl_sock); 116 errno = saved_errno; 117 return (0); 118 } 119 120 ibuf = xcalloc(1, sizeof(struct imsgbuf)); 121 imsg_init(ibuf, ctl_sock); 122 123 return (1); 124 } 125 126 int 127 srv_connected(void) 128 { 129 return ibuf != NULL ? 1 : 0; 130 } 131 132 FILE * 133 offline_file(void) 134 { 135 char path[PATH_MAX]; 136 int fd; 137 FILE *fp; 138 139 if (!bsnprintf(path, sizeof(path), "%s%s/%lld.XXXXXXXXXX", PATH_SPOOL, 140 PATH_OFFLINE, (long long)time(NULL))) 141 err(EX_UNAVAILABLE, "snprintf"); 142 143 if ((fd = mkstemp(path)) == -1 || (fp = fdopen(fd, "w+")) == NULL) { 144 if (fd != -1) 145 unlink(path); 146 err(EX_UNAVAILABLE, "cannot create temporary file %s", path); 147 } 148 149 if (fchmod(fd, 0600) == -1) { 150 unlink(path); 151 err(EX_SOFTWARE, "fchmod"); 152 } 153 154 return fp; 155 } 156 157 158 static void 159 srv_flush(void) 160 { 161 if (imsg_flush(ibuf) == -1) 162 err(1, "write error"); 163 } 164 165 static void 166 srv_send(int msg, const void *data, size_t len) 167 { 168 if (ibuf == NULL && !srv_connect()) 169 errx(1, "smtpd doesn't seem to be running"); 170 imsg_compose(ibuf, msg, IMSG_VERSION, 0, -1, data, len); 171 } 172 173 static void 174 srv_recv(int type) 175 { 176 ssize_t n; 177 178 srv_flush(); 179 180 while (1) { 181 if ((n = imsg_get(ibuf, &imsg)) == -1) 182 errx(1, "imsg_get error"); 183 if (n) { 184 if (imsg.hdr.type == IMSG_CTL_FAIL && 185 imsg.hdr.peerid != 0 && 186 imsg.hdr.peerid != IMSG_VERSION) 187 errx(1, "incompatible smtpctl and smtpd"); 188 if (type != -1 && type != (int)imsg.hdr.type) 189 errx(1, "bad message type"); 190 rdata = imsg.data; 191 rlen = imsg.hdr.len - sizeof(imsg.hdr); 192 break; 193 } 194 195 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 196 errx(1, "imsg_read error"); 197 if (n == 0) 198 errx(1, "pipe closed"); 199 } 200 } 201 202 static void 203 srv_read(void *dst, size_t sz) 204 { 205 if (sz == 0) 206 return; 207 if (rlen < sz) 208 errx(1, "message too short"); 209 if (dst) 210 memmove(dst, rdata, sz); 211 rlen -= sz; 212 rdata += sz; 213 } 214 215 static void 216 srv_get_int(int *i) 217 { 218 srv_read(i, sizeof(*i)); 219 } 220 221 static void 222 srv_get_time(time_t *t) 223 { 224 srv_read(t, sizeof(*t)); 225 } 226 227 static void 228 srv_get_evpid(uint64_t *evpid) 229 { 230 srv_read(evpid, sizeof(*evpid)); 231 } 232 233 static void 234 srv_get_string(const char **s) 235 { 236 const char *end; 237 size_t len; 238 239 if (rlen == 0) 240 errx(1, "message too short"); 241 242 rlen -= 1; 243 if (*rdata++ == '\0') { 244 *s = NULL; 245 return; 246 } 247 248 if (rlen == 0) 249 errx(1, "bogus string"); 250 251 end = memchr(rdata, 0, rlen); 252 if (end == NULL) 253 errx(1, "unterminated string"); 254 255 len = end + 1 - rdata; 256 257 *s = rdata; 258 rlen -= len; 259 rdata += len; 260 } 261 262 static void 263 srv_get_envelope(struct envelope *evp) 264 { 265 uint64_t evpid; 266 const char *str; 267 268 srv_get_evpid(&evpid); 269 srv_get_string(&str); 270 271 envelope_load_buffer(evp, str, strlen(str)); 272 evp->id = evpid; 273 } 274 275 static void 276 srv_end(void) 277 { 278 if (rlen) 279 errx(1, "bogus data"); 280 imsg_free(&imsg); 281 } 282 283 static int 284 srv_check_result(int verbose_) 285 { 286 srv_recv(-1); 287 srv_end(); 288 289 switch (imsg.hdr.type) { 290 case IMSG_CTL_OK: 291 if (verbose_) 292 printf("command succeeded\n"); 293 return (0); 294 case IMSG_CTL_FAIL: 295 if (verbose_) { 296 if (rlen) 297 printf("command failed: %s\n", rdata); 298 else 299 printf("command failed\n"); 300 } 301 return (1); 302 default: 303 errx(1, "wrong message in response: %u", imsg.hdr.type); 304 } 305 return (0); 306 } 307 308 static int 309 srv_iter_messages(uint32_t *res) 310 { 311 static uint32_t *msgids = NULL, from = 0; 312 static size_t n, curr; 313 static int done = 0; 314 315 if (done) 316 return (0); 317 318 if (msgids == NULL) { 319 srv_send(IMSG_CTL_LIST_MESSAGES, &from, sizeof(from)); 320 srv_recv(IMSG_CTL_LIST_MESSAGES); 321 if (rlen == 0) { 322 srv_end(); 323 done = 1; 324 return (0); 325 } 326 msgids = malloc(rlen); 327 n = rlen / sizeof(*msgids); 328 srv_read(msgids, rlen); 329 srv_end(); 330 331 curr = 0; 332 from = msgids[n - 1] + 1; 333 if (from == 0) 334 done = 1; 335 } 336 337 *res = msgids[curr++]; 338 if (curr == n) { 339 free(msgids); 340 msgids = NULL; 341 } 342 343 return (1); 344 } 345 346 static int 347 srv_iter_envelopes(uint32_t msgid, struct envelope *evp) 348 { 349 static uint32_t currmsgid = 0; 350 static uint64_t from = 0; 351 static int done = 0, need_send = 1, found; 352 int flags; 353 time_t nexttry; 354 355 if (currmsgid != msgid) { 356 if (currmsgid != 0 && !done) 357 errx(1, "must finish current iteration first"); 358 currmsgid = msgid; 359 from = msgid_to_evpid(msgid); 360 done = 0; 361 found = 0; 362 need_send = 1; 363 } 364 365 if (done) 366 return (0); 367 368 again: 369 if (need_send) { 370 found = 0; 371 srv_send(IMSG_CTL_LIST_ENVELOPES, &from, sizeof(from)); 372 } 373 need_send = 0; 374 375 srv_recv(IMSG_CTL_LIST_ENVELOPES); 376 if (rlen == 0) { 377 srv_end(); 378 if (!found || evpid_to_msgid(from) != msgid) { 379 done = 1; 380 return (0); 381 } 382 need_send = 1; 383 goto again; 384 } 385 386 srv_get_int(&flags); 387 srv_get_time(&nexttry); 388 srv_get_envelope(evp); 389 srv_end(); 390 391 evp->flags |= flags; 392 evp->nexttry = nexttry; 393 394 from = evp->id + 1; 395 found++; 396 return (1); 397 } 398 399 static int 400 srv_iter_evpids(uint32_t msgid, uint64_t *evpid, int *offset) 401 { 402 static uint64_t *evpids = NULL, *tmp; 403 static int n, tmpalloc, alloc = 0; 404 struct envelope evp; 405 406 if (*offset == 0) { 407 n = 0; 408 while (srv_iter_envelopes(msgid, &evp)) { 409 if (n == alloc) { 410 tmpalloc = alloc ? (alloc * 2) : 128; 411 tmp = recallocarray(evpids, alloc, tmpalloc, 412 sizeof(*evpids)); 413 if (tmp == NULL) 414 err(1, "recallocarray"); 415 evpids = tmp; 416 alloc = tmpalloc; 417 } 418 evpids[n++] = evp.id; 419 } 420 } 421 422 if (*offset >= n) 423 return (0); 424 *evpid = evpids[*offset]; 425 *offset += 1; 426 return (1); 427 } 428 429 static void 430 srv_foreach_envelope(struct parameter *argv, int ctl, size_t *total, size_t *ok) 431 { 432 uint32_t msgid; 433 uint64_t evpid; 434 int i; 435 436 *total = 0; 437 *ok = 0; 438 439 if (argv == NULL) { 440 while (srv_iter_messages(&msgid)) { 441 i = 0; 442 while (srv_iter_evpids(msgid, &evpid, &i)) { 443 *total += 1; 444 srv_send(ctl, &evpid, sizeof(evpid)); 445 if (srv_check_result(0) == 0) 446 *ok += 1; 447 } 448 } 449 } else if (argv->type == P_MSGID) { 450 i = 0; 451 while (srv_iter_evpids(argv->u.u_msgid, &evpid, &i)) { 452 srv_send(ctl, &evpid, sizeof(evpid)); 453 if (srv_check_result(0) == 0) 454 *ok += 1; 455 } 456 } else { 457 *total += 1; 458 srv_send(ctl, &argv->u.u_evpid, sizeof(evpid)); 459 if (srv_check_result(0) == 0) 460 *ok += 1; 461 } 462 } 463 464 static void 465 srv_show_cmd(int cmd, const void *data, size_t len) 466 { 467 int done = 0; 468 469 srv_send(cmd, data, len); 470 471 do { 472 srv_recv(cmd); 473 if (rlen) { 474 printf("%s\n", rdata); 475 srv_read(NULL, rlen); 476 } 477 else 478 done = 1; 479 srv_end(); 480 } while (!done); 481 } 482 483 static void 484 droppriv(void) 485 { 486 struct passwd *pw; 487 488 if (geteuid()) 489 return; 490 491 if ((pw = getpwnam(SMTPD_USER)) == NULL) 492 errx(1, "unknown user " SMTPD_USER); 493 494 if ((setgroups(1, &pw->pw_gid) || 495 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 496 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))) 497 err(1, "cannot drop privileges"); 498 } 499 500 static int 501 do_permission_denied(int argc, struct parameter *argv) 502 { 503 errx(1, "need root privileges"); 504 } 505 506 static int 507 do_log_brief(int argc, struct parameter *argv) 508 { 509 int v = 0; 510 511 srv_send(IMSG_CTL_VERBOSE, &v, sizeof(v)); 512 return srv_check_result(1); 513 } 514 515 static int 516 do_log_verbose(int argc, struct parameter *argv) 517 { 518 int v = TRACE_DEBUG; 519 520 srv_send(IMSG_CTL_VERBOSE, &v, sizeof(v)); 521 return srv_check_result(1); 522 } 523 524 static int 525 do_monitor(int argc, struct parameter *argv) 526 { 527 struct stat_digest last, digest; 528 size_t count; 529 530 memset(&last, 0, sizeof(last)); 531 count = 0; 532 533 while (1) { 534 srv_send(IMSG_CTL_GET_DIGEST, NULL, 0); 535 srv_recv(IMSG_CTL_GET_DIGEST); 536 srv_read(&digest, sizeof(digest)); 537 srv_end(); 538 539 if (count % 25 == 0) { 540 if (count != 0) 541 printf("\n"); 542 printf("--- client --- " 543 "-- envelope -- " 544 "---- relay/delivery --- " 545 "------- misc -------\n" 546 "curr conn disc " 547 "curr enq deq " 548 "ok tmpfail prmfail loop " 549 "expire remove bounce\n"); 550 } 551 printf("%4zu %4zu %4zu " 552 "%4zu %4zu %4zu " 553 "%4zu %4zu %4zu %4zu " 554 "%4zu %4zu %4zu\n", 555 digest.clt_connect - digest.clt_disconnect, 556 digest.clt_connect - last.clt_connect, 557 digest.clt_disconnect - last.clt_disconnect, 558 559 digest.evp_enqueued - digest.evp_dequeued, 560 digest.evp_enqueued - last.evp_enqueued, 561 digest.evp_dequeued - last.evp_dequeued, 562 563 digest.dlv_ok - last.dlv_ok, 564 digest.dlv_tempfail - last.dlv_tempfail, 565 digest.dlv_permfail - last.dlv_permfail, 566 digest.dlv_loop - last.dlv_loop, 567 568 digest.evp_expired - last.evp_expired, 569 digest.evp_removed - last.evp_removed, 570 digest.evp_bounce - last.evp_bounce); 571 572 last = digest; 573 count++; 574 sleep(1); 575 } 576 577 return (0); 578 } 579 580 static int 581 do_pause_envelope(int argc, struct parameter *argv) 582 { 583 size_t total, ok; 584 585 srv_foreach_envelope(argv, IMSG_CTL_PAUSE_EVP, &total, &ok); 586 printf("%zu envelope%s paused\n", ok, (ok > 1) ? "s" : ""); 587 588 return (0); 589 } 590 591 static int 592 do_pause_mda(int argc, struct parameter *argv) 593 { 594 srv_send(IMSG_CTL_PAUSE_MDA, NULL, 0); 595 return srv_check_result(1); 596 } 597 598 static int 599 do_pause_mta(int argc, struct parameter *argv) 600 { 601 srv_send(IMSG_CTL_PAUSE_MTA, NULL, 0); 602 return srv_check_result(1); 603 } 604 605 static int 606 do_pause_smtp(int argc, struct parameter *argv) 607 { 608 srv_send(IMSG_CTL_PAUSE_SMTP, NULL, 0); 609 return srv_check_result(1); 610 } 611 612 static int 613 do_profile(int argc, struct parameter *argv) 614 { 615 int v; 616 617 v = str_to_profile(argv[0].u.u_str); 618 619 srv_send(IMSG_CTL_PROFILE_ENABLE, &v, sizeof(v)); 620 return srv_check_result(1); 621 } 622 623 static int 624 do_remove(int argc, struct parameter *argv) 625 { 626 size_t total, ok; 627 628 srv_foreach_envelope(argv, IMSG_CTL_REMOVE, &total, &ok); 629 printf("%zu envelope%s removed\n", ok, (ok > 1) ? "s" : ""); 630 631 return (0); 632 } 633 634 static int 635 do_resume_envelope(int argc, struct parameter *argv) 636 { 637 size_t total, ok; 638 639 srv_foreach_envelope(argv, IMSG_CTL_RESUME_EVP, &total, &ok); 640 printf("%zu envelope%s resumed\n", ok, (ok > 1) ? "s" : ""); 641 642 return (0); 643 } 644 645 static int 646 do_resume_mda(int argc, struct parameter *argv) 647 { 648 srv_send(IMSG_CTL_RESUME_MDA, NULL, 0); 649 return srv_check_result(1); 650 } 651 652 static int 653 do_resume_mta(int argc, struct parameter *argv) 654 { 655 srv_send(IMSG_CTL_RESUME_MTA, NULL, 0); 656 return srv_check_result(1); 657 } 658 659 static int 660 do_resume_route(int argc, struct parameter *argv) 661 { 662 uint64_t v; 663 664 if (argc == 0) 665 v = 0; 666 else 667 v = argv[0].u.u_routeid; 668 669 srv_send(IMSG_CTL_RESUME_ROUTE, &v, sizeof(v)); 670 return srv_check_result(1); 671 } 672 673 static int 674 do_resume_smtp(int argc, struct parameter *argv) 675 { 676 srv_send(IMSG_CTL_RESUME_SMTP, NULL, 0); 677 return srv_check_result(1); 678 } 679 680 static int 681 do_schedule(int argc, struct parameter *argv) 682 { 683 size_t total, ok; 684 685 srv_foreach_envelope(argv, IMSG_CTL_SCHEDULE, &total, &ok); 686 printf("%zu envelope%s scheduled\n", ok, (ok > 1) ? "s" : ""); 687 688 return (0); 689 } 690 691 static int 692 do_show_envelope(int argc, struct parameter *argv) 693 { 694 char buf[PATH_MAX]; 695 696 if (!bsnprintf(buf, sizeof(buf), "%s%s/%02x/%08x/%016" PRIx64, 697 PATH_SPOOL, 698 PATH_QUEUE, 699 (evpid_to_msgid(argv[0].u.u_evpid) & 0xff000000) >> 24, 700 evpid_to_msgid(argv[0].u.u_evpid), 701 argv[0].u.u_evpid)) 702 errx(1, "unable to retrieve envelope"); 703 704 display(buf); 705 706 return (0); 707 } 708 709 static int 710 do_show_hoststats(int argc, struct parameter *argv) 711 { 712 srv_show_cmd(IMSG_CTL_MTA_SHOW_HOSTSTATS, NULL, 0); 713 714 return (0); 715 } 716 717 static int 718 do_show_message(int argc, struct parameter *argv) 719 { 720 char buf[PATH_MAX]; 721 uint32_t msgid; 722 723 if (argv[0].type == P_EVPID) 724 msgid = evpid_to_msgid(argv[0].u.u_evpid); 725 else 726 msgid = argv[0].u.u_msgid; 727 728 if (!bsnprintf(buf, sizeof(buf), "%s%s/%02x/%08x/message", 729 PATH_SPOOL, 730 PATH_QUEUE, 731 (msgid & 0xff000000) >> 24, 732 msgid)) 733 errx(1, "unable to retrieve message"); 734 735 display(buf); 736 737 return (0); 738 } 739 740 static int 741 do_show_queue(int argc, struct parameter *argv) 742 { 743 struct envelope evp; 744 uint32_t msgid; 745 FTS *fts; 746 FTSENT *ftse; 747 char *qpath[] = {"/queue", NULL}; 748 char *tmp; 749 uint64_t evpid; 750 751 now = time(NULL); 752 753 if (!srv_connect()) { 754 queue_init("fs", 0); 755 if (chroot(PATH_SPOOL) == -1 || chdir("/") == -1) 756 err(1, "%s", PATH_SPOOL); 757 fts = fts_open(qpath, FTS_PHYSICAL|FTS_NOCHDIR, NULL); 758 if (fts == NULL) 759 err(1, "%s/queue", PATH_SPOOL); 760 761 while ((ftse = fts_read(fts)) != NULL) { 762 switch (ftse->fts_info) { 763 case FTS_DP: 764 case FTS_DNR: 765 break; 766 case FTS_F: 767 tmp = NULL; 768 evpid = strtoull(ftse->fts_name, &tmp, 16); 769 if (tmp && *tmp != '\0') 770 break; 771 show_offline_envelope(evpid); 772 } 773 } 774 775 fts_close(fts); 776 return (0); 777 } 778 779 if (argc == 0) { 780 msgid = 0; 781 while (srv_iter_messages(&msgid)) 782 while (srv_iter_envelopes(msgid, &evp)) 783 show_queue_envelope(&evp, 1); 784 } else if (argv[0].type == P_MSGID) { 785 while (srv_iter_envelopes(argv[0].u.u_msgid, &evp)) 786 show_queue_envelope(&evp, 1); 787 } 788 789 return (0); 790 } 791 792 static int 793 do_show_hosts(int argc, struct parameter *argv) 794 { 795 srv_show_cmd(IMSG_CTL_MTA_SHOW_HOSTS, NULL, 0); 796 797 return (0); 798 } 799 800 static int 801 do_show_relays(int argc, struct parameter *argv) 802 { 803 srv_show_cmd(IMSG_CTL_MTA_SHOW_RELAYS, NULL, 0); 804 805 return (0); 806 } 807 808 static int 809 do_show_routes(int argc, struct parameter *argv) 810 { 811 srv_show_cmd(IMSG_CTL_MTA_SHOW_ROUTES, NULL, 0); 812 813 return (0); 814 } 815 816 static int 817 do_show_stats(int argc, struct parameter *argv) 818 { 819 struct stat_kv kv; 820 time_t duration; 821 822 memset(&kv, 0, sizeof kv); 823 824 while (1) { 825 srv_send(IMSG_CTL_GET_STATS, &kv, sizeof kv); 826 srv_recv(IMSG_CTL_GET_STATS); 827 srv_read(&kv, sizeof(kv)); 828 srv_end(); 829 830 if (kv.iter == NULL) 831 break; 832 833 if (strcmp(kv.key, "uptime") == 0) { 834 duration = time(NULL) - kv.val.u.counter; 835 printf("uptime=%lld\n", (long long)duration); 836 printf("uptime.human=%s\n", 837 duration_to_text(duration)); 838 } 839 else { 840 switch (kv.val.type) { 841 case STAT_COUNTER: 842 printf("%s=%zd\n", 843 kv.key, kv.val.u.counter); 844 break; 845 case STAT_TIMESTAMP: 846 printf("%s=%" PRId64 "\n", 847 kv.key, (int64_t)kv.val.u.timestamp); 848 break; 849 case STAT_TIMEVAL: 850 printf("%s=%lld.%lld\n", 851 kv.key, (long long)kv.val.u.tv.tv_sec, 852 (long long)kv.val.u.tv.tv_usec); 853 break; 854 case STAT_TIMESPEC: 855 printf("%s=%lld.%06ld\n", 856 kv.key, 857 (long long)kv.val.u.ts.tv_sec * 1000000 + 858 kv.val.u.ts.tv_nsec / 1000000, 859 kv.val.u.ts.tv_nsec % 1000000); 860 break; 861 } 862 } 863 } 864 865 return (0); 866 } 867 868 static int 869 do_show_status(int argc, struct parameter *argv) 870 { 871 uint32_t sc_flags; 872 873 srv_send(IMSG_CTL_SHOW_STATUS, NULL, 0); 874 srv_recv(IMSG_CTL_SHOW_STATUS); 875 srv_read(&sc_flags, sizeof(sc_flags)); 876 srv_end(); 877 printf("MDA %s\n", 878 (sc_flags & SMTPD_MDA_PAUSED) ? "paused" : "running"); 879 printf("MTA %s\n", 880 (sc_flags & SMTPD_MTA_PAUSED) ? "paused" : "running"); 881 printf("SMTP %s\n", 882 (sc_flags & SMTPD_SMTP_PAUSED) ? "paused" : "running"); 883 return (0); 884 } 885 886 static int 887 do_trace(int argc, struct parameter *argv) 888 { 889 int v; 890 891 v = str_to_trace(argv[0].u.u_str); 892 893 srv_send(IMSG_CTL_TRACE_ENABLE, &v, sizeof(v)); 894 return srv_check_result(1); 895 } 896 897 static int 898 do_unprofile(int argc, struct parameter *argv) 899 { 900 int v; 901 902 v = str_to_profile(argv[0].u.u_str); 903 904 srv_send(IMSG_CTL_PROFILE_DISABLE, &v, sizeof(v)); 905 return srv_check_result(1); 906 } 907 908 static int 909 do_untrace(int argc, struct parameter *argv) 910 { 911 int v; 912 913 v = str_to_trace(argv[0].u.u_str); 914 915 srv_send(IMSG_CTL_TRACE_DISABLE, &v, sizeof(v)); 916 return srv_check_result(1); 917 } 918 919 static int 920 do_update_table(int argc, struct parameter *argv) 921 { 922 const char *name = argv[0].u.u_str; 923 924 srv_send(IMSG_CTL_UPDATE_TABLE, name, strlen(name) + 1); 925 return srv_check_result(1); 926 } 927 928 static int 929 do_encrypt(int argc, struct parameter *argv) 930 { 931 const char *p = NULL; 932 933 droppriv(); 934 935 if (argv) 936 p = argv[0].u.u_str; 937 execl(PATH_ENCRYPT, "encrypt", "--", p, (char *)NULL); 938 errx(1, "execl"); 939 } 940 941 static int 942 do_block_mta(int argc, struct parameter *argv) 943 { 944 struct ibuf *m; 945 946 if (ibuf == NULL && !srv_connect()) 947 errx(1, "smtpd doesn't seem to be running"); 948 m = imsg_create(ibuf, IMSG_CTL_MTA_BLOCK, IMSG_VERSION, 0, 949 sizeof(argv[0].u.u_ss) + strlen(argv[1].u.u_str) + 1); 950 if (imsg_add(m, &argv[0].u.u_ss, sizeof(argv[0].u.u_ss)) == -1) 951 errx(1, "imsg_add"); 952 if (imsg_add(m, argv[1].u.u_str, strlen(argv[1].u.u_str) + 1) == -1) 953 errx(1, "imsg_add"); 954 imsg_close(ibuf, m); 955 956 return srv_check_result(1); 957 } 958 959 static int 960 do_unblock_mta(int argc, struct parameter *argv) 961 { 962 struct ibuf *m; 963 964 if (ibuf == NULL && !srv_connect()) 965 errx(1, "smtpd doesn't seem to be running"); 966 967 m = imsg_create(ibuf, IMSG_CTL_MTA_UNBLOCK, IMSG_VERSION, 0, 968 sizeof(argv[0].u.u_ss) + strlen(argv[1].u.u_str) + 1); 969 if (imsg_add(m, &argv[0].u.u_ss, sizeof(argv[0].u.u_ss)) == -1) 970 errx(1, "imsg_add"); 971 if (imsg_add(m, argv[1].u.u_str, strlen(argv[1].u.u_str) + 1) == -1) 972 errx(1, "imsg_add"); 973 imsg_close(ibuf, m); 974 975 return srv_check_result(1); 976 } 977 978 static int 979 do_show_mta_block(int argc, struct parameter *argv) 980 { 981 srv_show_cmd(IMSG_CTL_MTA_SHOW_BLOCK, NULL, 0); 982 983 return (0); 984 } 985 986 static int 987 do_discover(int argc, struct parameter *argv) 988 { 989 uint64_t evpid; 990 uint32_t msgid; 991 size_t n_evp; 992 993 if (ibuf == NULL && !srv_connect()) 994 errx(1, "smtpd doesn't seem to be running"); 995 996 if (argv[0].type == P_EVPID) { 997 evpid = argv[0].u.u_evpid; 998 srv_send(IMSG_CTL_DISCOVER_EVPID, &evpid, sizeof evpid); 999 srv_recv(IMSG_CTL_DISCOVER_EVPID); 1000 } else { 1001 msgid = argv[0].u.u_msgid; 1002 srv_send(IMSG_CTL_DISCOVER_MSGID, &msgid, sizeof msgid); 1003 srv_recv(IMSG_CTL_DISCOVER_MSGID); 1004 } 1005 1006 if (rlen == 0) { 1007 srv_end(); 1008 return (0); 1009 } else { 1010 srv_read(&n_evp, sizeof n_evp); 1011 srv_end(); 1012 } 1013 1014 printf("%zu envelope%s discovered\n", n_evp, (n_evp != 1) ? "s" : ""); 1015 return (0); 1016 } 1017 1018 static int 1019 do_spf_walk(int argc, struct parameter *argv) 1020 { 1021 droppriv(); 1022 1023 return spfwalk(argc, argv); 1024 } 1025 1026 #define cmd_install_priv(s, f) \ 1027 cmd_install((s), privileged ? (f) : do_permission_denied) 1028 1029 int 1030 main(int argc, char **argv) 1031 { 1032 gid_t gid; 1033 int privileged; 1034 char *argv_mailq[] = { "show", "queue", NULL }; 1035 1036 log_init(1, LOG_MAIL); 1037 1038 sendmail_compat(argc, argv); 1039 privileged = geteuid() == 0; 1040 1041 gid = getgid(); 1042 if (setresgid(gid, gid, gid) == -1) 1043 err(1, "setresgid"); 1044 1045 /* Privileged commands */ 1046 cmd_install_priv("discover <evpid>", do_discover); 1047 cmd_install_priv("discover <msgid>", do_discover); 1048 cmd_install_priv("pause mta from <addr> for <str>", do_block_mta); 1049 cmd_install_priv("resume mta from <addr> for <str>", do_unblock_mta); 1050 cmd_install_priv("show mta paused", do_show_mta_block); 1051 cmd_install_priv("log brief", do_log_brief); 1052 cmd_install_priv("log verbose", do_log_verbose); 1053 cmd_install_priv("monitor", do_monitor); 1054 cmd_install_priv("pause envelope <evpid>", do_pause_envelope); 1055 cmd_install_priv("pause envelope <msgid>", do_pause_envelope); 1056 cmd_install_priv("pause envelope all", do_pause_envelope); 1057 cmd_install_priv("pause mda", do_pause_mda); 1058 cmd_install_priv("pause mta", do_pause_mta); 1059 cmd_install_priv("pause smtp", do_pause_smtp); 1060 cmd_install_priv("profile <str>", do_profile); 1061 cmd_install_priv("remove <evpid>", do_remove); 1062 cmd_install_priv("remove <msgid>", do_remove); 1063 cmd_install_priv("remove all", do_remove); 1064 cmd_install_priv("resume envelope <evpid>", do_resume_envelope); 1065 cmd_install_priv("resume envelope <msgid>", do_resume_envelope); 1066 cmd_install_priv("resume envelope all", do_resume_envelope); 1067 cmd_install_priv("resume mda", do_resume_mda); 1068 cmd_install_priv("resume mta", do_resume_mta); 1069 cmd_install_priv("resume route <routeid>", do_resume_route); 1070 cmd_install_priv("resume smtp", do_resume_smtp); 1071 cmd_install_priv("schedule <msgid>", do_schedule); 1072 cmd_install_priv("schedule <evpid>", do_schedule); 1073 cmd_install_priv("schedule all", do_schedule); 1074 cmd_install_priv("show envelope <evpid>", do_show_envelope); 1075 cmd_install_priv("show hoststats", do_show_hoststats); 1076 cmd_install_priv("show message <msgid>", do_show_message); 1077 cmd_install_priv("show message <evpid>", do_show_message); 1078 cmd_install_priv("show queue", do_show_queue); 1079 cmd_install_priv("show queue <msgid>", do_show_queue); 1080 cmd_install_priv("show hosts", do_show_hosts); 1081 cmd_install_priv("show relays", do_show_relays); 1082 cmd_install_priv("show routes", do_show_routes); 1083 cmd_install_priv("show stats", do_show_stats); 1084 cmd_install_priv("show status", do_show_status); 1085 cmd_install_priv("trace <str>", do_trace); 1086 cmd_install_priv("unprofile <str>", do_unprofile); 1087 cmd_install_priv("untrace <str>", do_untrace); 1088 cmd_install_priv("update table <str>", do_update_table); 1089 1090 /* Unprivileged commands */ 1091 cmd_install("encrypt", do_encrypt); 1092 cmd_install("encrypt <str>", do_encrypt); 1093 cmd_install("spf walk", do_spf_walk); 1094 1095 if (strcmp(__progname, "mailq") == 0) 1096 return cmd_run(2, argv_mailq); 1097 if (strcmp(__progname, "smtpctl") == 0) 1098 return cmd_run(argc - 1, argv + 1); 1099 1100 errx(1, "unsupported mode"); 1101 return (0); 1102 } 1103 1104 void 1105 sendmail_compat(int argc, char **argv) 1106 { 1107 FILE *offlinefp = NULL; 1108 gid_t gid; 1109 int i, r; 1110 1111 if (strcmp(__progname, "sendmail") == 0 || 1112 strcmp(__progname, "send-mail") == 0) { 1113 /* 1114 * determine whether we are called with flags 1115 * that should invoke makemap/newaliases. 1116 */ 1117 for (i = 1; i < argc; i++) 1118 if (strncmp(argv[i], "-bi", 3) == 0) 1119 exit(makemap(P_SENDMAIL, argc, argv)); 1120 1121 if (!srv_connect()) 1122 offlinefp = offline_file(); 1123 1124 gid = getgid(); 1125 if (setresgid(gid, gid, gid) == -1) 1126 err(1, "setresgid"); 1127 1128 /* we'll reduce further down the road */ 1129 if (pledge("stdio rpath wpath cpath tmppath flock " 1130 "dns getpw recvfd", NULL) == -1) 1131 err(1, "pledge"); 1132 1133 sendmail = 1; 1134 exit(enqueue(argc, argv, offlinefp)); 1135 } else if (strcmp(__progname, "makemap") == 0) 1136 exit(makemap(P_MAKEMAP, argc, argv)); 1137 else if (strcmp(__progname, "newaliases") == 0) { 1138 r = makemap(P_NEWALIASES, argc, argv); 1139 /* 1140 * if server is available, notify of table update. 1141 * only makes sense for static tables AND if server is up. 1142 */ 1143 if (srv_connect()) { 1144 srv_send(IMSG_CTL_UPDATE_TABLE, "aliases", strlen("aliases") + 1); 1145 srv_check_result(0); 1146 } 1147 exit(r); 1148 } 1149 } 1150 1151 static void 1152 show_queue_envelope(struct envelope *e, int online) 1153 { 1154 const char *src = "?", *agent = "?"; 1155 char status[128], runstate[128], errline[LINE_MAX]; 1156 1157 status[0] = '\0'; 1158 1159 getflag(&e->flags, EF_BOUNCE, "bounce", status, sizeof(status)); 1160 getflag(&e->flags, EF_AUTHENTICATED, "auth", status, sizeof(status)); 1161 getflag(&e->flags, EF_INTERNAL, "internal", status, sizeof(status)); 1162 getflag(&e->flags, EF_SUSPEND, "suspend", status, sizeof(status)); 1163 getflag(&e->flags, EF_HOLD, "hold", status, sizeof(status)); 1164 1165 if (online) { 1166 if (e->flags & EF_PENDING) 1167 (void)snprintf(runstate, sizeof runstate, "pending|%zd", 1168 (ssize_t)(e->nexttry - now)); 1169 else if (e->flags & EF_INFLIGHT) 1170 (void)snprintf(runstate, sizeof runstate, 1171 "inflight|%zd", (ssize_t)(now - e->lasttry)); 1172 else 1173 (void)snprintf(runstate, sizeof runstate, "invalid|"); 1174 e->flags &= ~(EF_PENDING|EF_INFLIGHT); 1175 } 1176 else 1177 (void)strlcpy(runstate, "offline|", sizeof runstate); 1178 1179 if (e->flags) 1180 errx(1, "%016" PRIx64 ": unexpected flags 0x%04x", e->id, 1181 e->flags); 1182 1183 if (status[0]) 1184 status[strlen(status) - 1] = '\0'; 1185 1186 if (e->type == D_MDA) 1187 agent = "mda"; 1188 else if (e->type == D_MTA) 1189 agent = "mta"; 1190 else if (e->type == D_BOUNCE) 1191 agent = "bounce"; 1192 1193 if (e->ss.ss_family == AF_LOCAL) 1194 src = "local"; 1195 else if (e->ss.ss_family == AF_INET) 1196 src = "inet4"; 1197 else if (e->ss.ss_family == AF_INET6) 1198 src = "inet6"; 1199 1200 strnvis(errline, e->errorline, sizeof(errline), 0); 1201 1202 printf("%016"PRIx64 1203 "|%s|%s|%s|%s@%s|%s@%s|%s@%s" 1204 "|%zu|%zu|%zu|%zu|%s|%s\n", 1205 1206 e->id, 1207 1208 src, 1209 agent, 1210 status, 1211 e->sender.user, e->sender.domain, 1212 e->rcpt.user, e->rcpt.domain, 1213 e->dest.user, e->dest.domain, 1214 1215 (size_t) e->creation, 1216 (size_t) (e->creation + e->ttl), 1217 (size_t) e->lasttry, 1218 (size_t) e->retry, 1219 runstate, 1220 errline); 1221 } 1222 1223 static void 1224 getflag(uint *bitmap, int bit, char *bitstr, char *buf, size_t len) 1225 { 1226 if (*bitmap & bit) { 1227 *bitmap &= ~bit; 1228 (void)strlcat(buf, bitstr, len); 1229 (void)strlcat(buf, ",", len); 1230 } 1231 } 1232 1233 static void 1234 show_offline_envelope(uint64_t evpid) 1235 { 1236 FILE *fp = NULL; 1237 char pathname[PATH_MAX]; 1238 size_t plen; 1239 char *p; 1240 size_t buflen; 1241 char buffer[sizeof(struct envelope)]; 1242 1243 struct envelope evp; 1244 1245 if (!bsnprintf(pathname, sizeof pathname, 1246 "/queue/%02x/%08x/%016"PRIx64, 1247 (evpid_to_msgid(evpid) & 0xff000000) >> 24, 1248 evpid_to_msgid(evpid), evpid)) 1249 goto end; 1250 fp = fopen(pathname, "r"); 1251 if (fp == NULL) 1252 goto end; 1253 1254 buflen = fread(buffer, 1, sizeof (buffer) - 1, fp); 1255 p = buffer; 1256 plen = buflen; 1257 buffer[buflen] = '\0'; 1258 1259 if (is_encrypted_buffer(p)) { 1260 warnx("offline encrypted queue is not supported yet"); 1261 goto end; 1262 } 1263 1264 if (is_gzip_buffer(p)) { 1265 warnx("offline compressed queue is not supported yet"); 1266 goto end; 1267 } 1268 1269 if (!envelope_load_buffer(&evp, p, plen)) 1270 goto end; 1271 evp.id = evpid; 1272 show_queue_envelope(&evp, 0); 1273 1274 end: 1275 if (fp) 1276 fclose(fp); 1277 } 1278 1279 static void 1280 display(const char *s) 1281 { 1282 FILE *fp; 1283 char *key; 1284 int gzipped; 1285 char *gzcat_argv0 = strrchr(PATH_GZCAT, '/') + 1; 1286 1287 if ((fp = fopen(s, "r")) == NULL) 1288 err(1, "fopen"); 1289 1290 if (is_encrypted_fp(fp)) { 1291 int i; 1292 FILE *ofp = NULL; 1293 1294 if ((ofp = tmpfile()) == NULL) 1295 err(1, "tmpfile"); 1296 1297 for (i = 0; i < 3; i++) { 1298 key = getpass("key> "); 1299 if (crypto_setup(key, strlen(key))) 1300 break; 1301 } 1302 if (i == 3) 1303 errx(1, "crypto-setup: invalid key"); 1304 1305 if (!crypto_decrypt_file(fp, ofp)) { 1306 printf("object is encrypted: %s\n", key); 1307 exit(1); 1308 } 1309 1310 fclose(fp); 1311 fp = ofp; 1312 fseek(fp, 0, SEEK_SET); 1313 } 1314 gzipped = is_gzip_fp(fp); 1315 1316 lseek(fileno(fp), 0, SEEK_SET); 1317 (void)dup2(fileno(fp), STDIN_FILENO); 1318 if (gzipped) 1319 execl(PATH_GZCAT, gzcat_argv0, (char *)NULL); 1320 else 1321 execl(PATH_CAT, "cat", (char *)NULL); 1322 err(1, "execl"); 1323 } 1324 1325 static int 1326 str_to_trace(const char *str) 1327 { 1328 if (!strcmp(str, "imsg")) 1329 return TRACE_IMSG; 1330 if (!strcmp(str, "io")) 1331 return TRACE_IO; 1332 if (!strcmp(str, "smtp")) 1333 return TRACE_SMTP; 1334 if (!strcmp(str, "filters")) 1335 return TRACE_FILTERS; 1336 if (!strcmp(str, "mta")) 1337 return TRACE_MTA; 1338 if (!strcmp(str, "bounce")) 1339 return TRACE_BOUNCE; 1340 if (!strcmp(str, "scheduler")) 1341 return TRACE_SCHEDULER; 1342 if (!strcmp(str, "lookup")) 1343 return TRACE_LOOKUP; 1344 if (!strcmp(str, "stat")) 1345 return TRACE_STAT; 1346 if (!strcmp(str, "rules")) 1347 return TRACE_RULES; 1348 if (!strcmp(str, "mproc")) 1349 return TRACE_MPROC; 1350 if (!strcmp(str, "expand")) 1351 return TRACE_EXPAND; 1352 if (!strcmp(str, "all")) 1353 return ~TRACE_DEBUG; 1354 errx(1, "invalid trace keyword: %s", str); 1355 return (0); 1356 } 1357 1358 static int 1359 str_to_profile(const char *str) 1360 { 1361 if (!strcmp(str, "imsg")) 1362 return PROFILE_IMSG; 1363 if (!strcmp(str, "queue")) 1364 return PROFILE_QUEUE; 1365 errx(1, "invalid profile keyword: %s", str); 1366 return (0); 1367 } 1368 1369 static int 1370 is_gzip_buffer(const char *buffer) 1371 { 1372 uint16_t magic; 1373 1374 memcpy(&magic, buffer, sizeof magic); 1375 #define GZIP_MAGIC 0x8b1f 1376 return (magic == GZIP_MAGIC); 1377 } 1378 1379 static int 1380 is_gzip_fp(FILE *fp) 1381 { 1382 uint8_t magic[2]; 1383 int ret = 0; 1384 1385 if (fread(&magic, 1, sizeof magic, fp) != sizeof magic) 1386 goto end; 1387 1388 ret = is_gzip_buffer((const char *)&magic); 1389 end: 1390 fseek(fp, 0, SEEK_SET); 1391 return ret; 1392 } 1393 1394 1395 /* XXX */ 1396 /* 1397 * queue supports transparent encryption. 1398 * encrypted chunks are prefixed with an API version byte 1399 * which we ensure is unambiguous with gzipped / plain 1400 * objects. 1401 */ 1402 1403 static int 1404 is_encrypted_buffer(const char *buffer) 1405 { 1406 uint8_t magic; 1407 1408 magic = *buffer; 1409 #define ENCRYPTION_MAGIC 0x1 1410 return (magic == ENCRYPTION_MAGIC); 1411 } 1412 1413 static int 1414 is_encrypted_fp(FILE *fp) 1415 { 1416 uint8_t magic; 1417 int ret = 0; 1418 1419 if (fread(&magic, 1, sizeof magic, fp) != sizeof magic) 1420 goto end; 1421 1422 ret = is_encrypted_buffer((const char *)&magic); 1423 end: 1424 fseek(fp, 0, SEEK_SET); 1425 return ret; 1426 } 1427