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