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