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