xref: /openbsd/usr.sbin/smtpd/smtpctl.c (revision 4bdff4be)
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