1/*	$NetBSD: postqueue.c,v 1.5 2023/12/23 20:30:44 christos Exp $	*/
2
3/*++
4/* NAME
5/*	postqueue 1
6/* SUMMARY
7/*	Postfix queue control
8/* SYNOPSIS
9/* .ti -4
10/*	\fBTo flush the mail queue\fR:
11/*
12/*	\fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-f\fR
13/*
14/*	\fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-i \fIqueue_id\fR
15/*
16/*	\fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-s \fIsite\fR
17/*
18/* .ti -4
19/*	\fBTo list the mail queue\fR:
20/*
21/*	\fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-j\fR
22/*
23/*	\fBpostqueue\fR [\fB-v\fR] [\fB-c \fIconfig_dir\fR] \fB-p\fR
24/* DESCRIPTION
25/*	The \fBpostqueue\fR(1) command implements the Postfix user interface
26/*	for queue management. It implements operations that are
27/*	traditionally available via the \fBsendmail\fR(1) command.
28/*	See the \fBpostsuper\fR(1) command for queue operations
29/*	that require super-user privileges such as deleting a message
30/*	from the queue or changing the status of a message.
31/*
32/*	The following options are recognized:
33/* .IP "\fB-c \fIconfig_dir\fR"
34/*	The \fBmain.cf\fR configuration file is in the named directory
35/*	instead of the default configuration directory. See also the
36/*	MAIL_CONFIG environment setting below.
37/* .IP \fB-f\fR
38/*	Flush the queue: attempt to deliver all queued mail.
39/*
40/*	This option implements the traditional "\fBsendmail -q\fR" command,
41/*	by contacting the Postfix \fBqmgr\fR(8) daemon.
42/*
43/*	Warning: flushing undeliverable mail frequently will result in
44/*	poor delivery performance of all other mail.
45/* .IP "\fB-i \fIqueue_id\fR"
46/*	Schedule immediate delivery of deferred mail with the
47/*	specified queue ID.
48/*
49/*	This option implements the traditional \fBsendmail -qI\fR
50/*	command, by contacting the \fBflush\fR(8) server.
51/*
52/*	This feature is available with Postfix version 2.4 and later.
53/* .IP "\fB-j\fR"
54/*	Produce a queue listing in JSON LINES format, based on
55/*	output from the showq(8) daemon. See "\fBJSON OBJECT
56/*	FORMAT\fR" below for details.
57/*
58/*	This feature is available in Postfix 3.1 and later.
59/* .IP \fB-p\fR
60/*	Produce a traditional sendmail-style queue listing.
61/*	This option implements the traditional \fBmailq\fR command,
62/*	by contacting the Postfix \fBshowq\fR(8) daemon.
63/*
64/*	Each queue entry shows the queue file ID, message
65/*	size, arrival time, sender, and the recipients that still need to
66/*	be delivered.  If mail could not be delivered upon the last attempt,
67/*	the reason for failure is shown. The queue ID string
68/*	is followed by an optional status character:
69/* .RS
70/* .IP \fB*\fR
71/*	The message is in the \fBactive\fR queue, i.e. the message is
72/*	selected for delivery.
73/* .IP \fB!\fR
74/*	The message is in the \fBhold\fR queue, i.e. no further delivery
75/*	attempt will be made until the mail is taken off hold.
76/* .IP \fB#\fR
77/*	The message is forced to expire. See the \fBpostsuper\fR(1)
78/*	options \fB-e\fR or \fB-f\fR.
79/* .sp
80/*	This feature is available in Postfix 3.5 and later.
81/* .RE
82/* .IP "\fB-s \fIsite\fR"
83/*	Schedule immediate delivery of all mail that is queued for the named
84/*	\fIsite\fR. A numerical site must be specified as a valid RFC 5321
85/*	address literal enclosed in [], just like in email addresses.
86/*	The site must be eligible for the "fast flush" service.
87/*	See \fBflush\fR(8) for more information about the "fast flush"
88/*	service.
89/*
90/*	This option implements the traditional "\fBsendmail -qR\fIsite\fR"
91/*	command, by contacting the Postfix \fBflush\fR(8) daemon.
92/* .IP \fB-v\fR
93/*	Enable verbose logging for debugging purposes. Multiple \fB-v\fR
94/*	options make the software increasingly verbose. As of Postfix 2.3,
95/*	this option is available for the super-user only.
96/* JSON OBJECT FORMAT
97/* .ad
98/* .fi
99/*	Each JSON object represents one queue file; it is emitted
100/*	as a single text line followed by a newline character.
101/*
102/*	Object members have string values unless indicated otherwise.
103/*	Programs should ignore object members that are not listed
104/*	here; the list of members is expected to grow over time.
105/* .IP \fBqueue_name\fR
106/*	The name of the queue where the message was found.  Note
107/*	that the contents of the mail queue may change while it is
108/*	being listed; some messages may appear more than once, and
109/*	some messages may be missed.
110/* .IP \fBqueue_id\fR
111/*	The queue file name. The queue_id may be reused within a
112/*	Postfix instance unless "enable_long_queue_ids = true" and
113/*	time is monotonic.  Even then, the queue_id is not expected
114/*	to be unique between different Postfix instances.  Management
115/*	tools that require a unique name should combine the queue_id
116/*	with the myhostname setting of the Postfix instance.
117/* .IP \fBarrival_time\fR
118/*	The number of seconds since the start of the UNIX epoch.
119/* .IP \fBmessage_size\fR
120/*	The number of bytes in the message header and body. This
121/*	number does not include message envelope information. It
122/*	is approximately equal to the number of bytes that would
123/*	be transmitted via SMTP including the <CR><LF> line endings.
124/* .IP \fBforced_expire\fR
125/*	The message is forced to expire (\fBtrue\fR or \fBfalse\fR).
126/*	See the \fBpostsuper\fR(1) options \fB-e\fR or \fB-f\fR.
127/* .sp
128/*	This feature is available in Postfix 3.5 and later.
129/* .IP \fBsender\fR
130/*	The envelope sender address.
131/* .IP \fBrecipients\fR
132/*	An array containing zero or more objects with members:
133/* .RS
134/* .IP \fBaddress\fR
135/*	One recipient address.
136/* .IP \fBdelay_reason\fR
137/*	If present, the reason for delayed delivery.  Delayed
138/*	recipients may have no delay reason, for example, while
139/*	delivery is in progress, or after the system was stopped
140/*	before it could record the reason.
141/* .RE
142/* SECURITY
143/* .ad
144/* .fi
145/*	This program is designed to run with set-group ID privileges, so
146/*	that it can connect to Postfix daemon processes.
147/* STANDARDS
148/*	RFC 7159 (JSON notation)
149/* DIAGNOSTICS
150/*	Problems are logged to \fBsyslogd\fR(8) or \fBpostlogd\fR(8),
151/*	and to the standard error stream.
152/* ENVIRONMENT
153/* .ad
154/* .fi
155/* .IP MAIL_CONFIG
156/*	Directory with the \fBmain.cf\fR file. In order to avoid exploitation
157/*	of set-group ID privileges, a non-standard directory is allowed only
158/*	if:
159/* .RS
160/* .IP \(bu
161/*	The name is listed in the standard \fBmain.cf\fR file with the
162/*	\fBalternate_config_directories\fR configuration parameter.
163/* .IP \(bu
164/*	The command is invoked by the super-user.
165/* .RE
166/* CONFIGURATION PARAMETERS
167/* .ad
168/* .fi
169/*	The following \fBmain.cf\fR parameters are especially relevant to
170/*	this program.
171/*	The text below provides only a parameter summary. See
172/*	\fBpostconf\fR(5) for more details including examples.
173/* .IP "\fBalternate_config_directories (empty)\fR"
174/*	A list of non-default Postfix configuration directories that may
175/*	be specified with "-c config_directory" on the command line (in the
176/*	case of \fBsendmail\fR(1), with the "-C" option), or via the MAIL_CONFIG
177/*	environment parameter.
178/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
179/*	The default location of the Postfix main.cf and master.cf
180/*	configuration files.
181/* .IP "\fBcommand_directory (see 'postconf -d' output)\fR"
182/*	The location of all postfix administrative commands.
183/* .IP "\fBfast_flush_domains ($relay_domains)\fR"
184/*	Optional list of destinations that are eligible for per-destination
185/*	logfiles with mail that is queued to those destinations.
186/* .IP "\fBimport_environment (see 'postconf -d' output)\fR"
187/*	The list of environment variables that a privileged Postfix
188/*	process will import from a non-Postfix parent process, or name=value
189/*	environment overrides.
190/* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
191/*	The location of the Postfix top-level queue directory.
192/* .IP "\fBsyslog_facility (mail)\fR"
193/*	The syslog facility of Postfix logging.
194/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
195/*	A prefix that is prepended to the process name in syslog
196/*	records, so that, for example, "smtpd" becomes "prefix/smtpd".
197/* .IP "\fBtrigger_timeout (10s)\fR"
198/*	The time limit for sending a trigger to a Postfix daemon (for
199/*	example, the \fBpickup\fR(8) or \fBqmgr\fR(8) daemon).
200/* .PP
201/*	Available in Postfix version 2.2 and later:
202/* .IP "\fBauthorized_flush_users (static:anyone)\fR"
203/*	List of users who are authorized to flush the queue.
204/* .IP "\fBauthorized_mailq_users (static:anyone)\fR"
205/*	List of users who are authorized to view the queue.
206/* FILES
207/*	/var/spool/postfix, mail queue
208/* SEE ALSO
209/*	qmgr(8), queue manager
210/*	showq(8), list mail queue
211/*	flush(8), fast flush service
212/*	sendmail(1), Sendmail-compatible user interface
213/*	postsuper(1), privileged queue operations
214/*	postlogd(8), Postfix logging
215/*	syslogd(8), system logging
216/* README FILES
217/* .ad
218/* .fi
219/*	Use "\fBpostconf readme_directory\fR" or
220/*	"\fBpostconf html_directory\fR" to locate this information.
221/* .na
222/* .nf
223/*	ETRN_README, Postfix ETRN howto
224/* LICENSE
225/* .ad
226/* .fi
227/*	The Secure Mailer license must be distributed with this software.
228/* HISTORY
229/* .ad
230/* .fi
231/*	The postqueue command was introduced with Postfix version 1.1.
232/* AUTHOR(S)
233/*	Wietse Venema
234/*	IBM T.J. Watson Research
235/*	P.O. Box 704
236/*	Yorktown Heights, NY 10598, USA
237/*
238/*	Wietse Venema
239/*	Google, Inc.
240/*	111 8th Avenue
241/*	New York, NY 10011, USA
242/*--*/
243
244/* System library. */
245
246#include <sys_defs.h>
247#include <sys/stat.h>
248#include <unistd.h>
249#include <string.h>
250#include <stdlib.h>
251#include <signal.h>
252#include <sysexits.h>
253#include <errno.h>
254
255/* Utility library. */
256
257#include <msg.h>
258#include <mymalloc.h>
259#include <clean_env.h>
260#include <vstream.h>
261#include <msg_vstream.h>
262#include <argv.h>
263#include <safe.h>
264#include <connect.h>
265#include <valid_hostname.h>
266#include <warn_stat.h>
267#include <events.h>
268#include <stringops.h>
269
270/* Global library. */
271
272#include <mail_proto.h>
273#include <mail_params.h>
274#include <mail_version.h>
275#include <mail_conf.h>
276#include <mail_task.h>
277#include <mail_run.h>
278#include <mail_flush.h>
279#include <mail_queue.h>
280#include <flush_clnt.h>
281#include <smtp_stream.h>
282#include <user_acl.h>
283#include <valid_mailhost_addr.h>
284#include <mail_dict.h>
285#include <mail_parm_split.h>
286#include <maillog_client.h>
287
288/* Application-specific. */
289
290#include <postqueue.h>
291
292 /*
293  * WARNING WARNING WARNING
294  *
295  * This software is designed to run set-gid. In order to avoid exploitation of
296  * privilege, this software should not run any external commands, nor should
297  * it take any information from the user, unless that information can be
298  * properly sanitized. To get an idea of how much information a process can
299  * inherit from a potentially hostile user, examine all the members of the
300  * process structure (typically, in /usr/include/sys/proc.h): the current
301  * directory, open files, timers, signals, environment, command line, umask,
302  * and so on.
303  */
304
305 /*
306  * Modes of operation.
307  *
308  * XXX To support flush by recipient domain, or for destinations that have no
309  * mapping to logfile, the server has to defend against resource exhaustion
310  * attacks. A malicious user could fork off a postqueue client that starts
311  * an expensive requests and then kills the client immediately; this way she
312  * could create a high Postfix load on the system without ever exceeding her
313  * own per-user process limit. To prevent this, either the server needs to
314  * establish frequent proof of client liveliness with challenge/response, or
315  * the client needs to restrict expensive requests to privileged users only.
316  *
317  * We don't have this problem with queue listings. The showq server detects an
318  * EPIPE error after reporting a few queue entries.
319  */
320#define PQ_MODE_DEFAULT		0	/* noop */
321#define PQ_MODE_MAILQ_LIST	1	/* list mail queue */
322#define PQ_MODE_FLUSH_QUEUE	2	/* flush queue */
323#define PQ_MODE_FLUSH_SITE	3	/* flush site */
324#define PQ_MODE_FLUSH_FILE	4	/* flush message */
325#define PQ_MODE_JSON_LIST	5	/* JSON-format queue listing */
326
327 /*
328  * Silly little macros (SLMs).
329  */
330#define STR	vstring_str
331
332 /*
333  * Queue manipulation access lists.
334  */
335char   *var_flush_acl;
336char   *var_showq_acl;
337
338static const CONFIG_STR_TABLE str_table[] = {
339    VAR_FLUSH_ACL, DEF_FLUSH_ACL, &var_flush_acl, 0, 0,
340    VAR_SHOWQ_ACL, DEF_SHOWQ_ACL, &var_showq_acl, 0, 0,
341    0,
342};
343
344/* showq_client - run the appropriate showq protocol client */
345
346static void showq_client(int mode, VSTREAM *showq)
347{
348    if (attr_scan(showq, ATTR_FLAG_STRICT,
349		  RECV_ATTR_STREQ(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_SHOWQ),
350		  ATTR_TYPE_END) != 0)
351	msg_fatal_status(EX_SOFTWARE, "malformed showq server response");
352    switch (mode) {
353    case PQ_MODE_MAILQ_LIST:
354	showq_compat(showq);
355	break;
356    case PQ_MODE_JSON_LIST:
357	showq_json(showq);
358	break;
359    default:
360	msg_panic("show_queue: unknown mode %d", mode);
361    }
362}
363
364/* show_queue - show queue status */
365
366static void show_queue(int mode)
367{
368    const char *errstr;
369    VSTREAM *showq;
370    int     n;
371    uid_t   uid = getuid();
372
373    if (uid != 0 && uid != var_owner_uid
374	&& (errstr = check_user_acl_byuid(VAR_SHOWQ_ACL, var_showq_acl,
375					  uid)) != 0)
376	msg_fatal_status(EX_NOPERM,
377		       "User %s(%ld) is not allowed to view the mail queue",
378			 errstr, (long) uid);
379
380    /*
381     * Connect to the show queue service.
382     */
383    if ((showq = mail_connect(MAIL_CLASS_PUBLIC, var_showq_service, BLOCKING)) != 0) {
384	showq_client(mode, showq);
385	if (vstream_fclose(showq))
386	    msg_warn("close: %m");
387    }
388
389    /*
390     * Don't assume that the mail system is down when the user has
391     * insufficient permission to access the showq socket.
392     */
393    else if (errno == EACCES || errno == EPERM) {
394	msg_fatal_status(EX_SOFTWARE,
395			 "Connect to the %s %s service: %m",
396			 var_mail_name, var_showq_service);
397    }
398
399    /*
400     * When the mail system is down, the superuser can still access the queue
401     * directly. Just run the showq program in stand-alone mode.
402     */
403    else if (geteuid() == 0) {
404	char   *showq_path;
405	ARGV   *argv;
406	int     stat;
407
408	msg_warn("Mail system is down -- accessing queue directly"
409		 " (Connect to the %s %s service: %m)",
410		 var_mail_name, var_showq_service);
411	showq_path = concatenate(var_daemon_dir, "/", var_showq_service,
412				 (char *) 0);
413	argv = argv_alloc(6);
414	argv_add(argv, showq_path, "-u", "-S", (char *) 0);
415	for (n = 0; n < msg_verbose; n++)
416	    argv_add(argv, "-v", (char *) 0);
417	argv_terminate(argv);
418	if ((showq = vstream_popen(O_RDONLY,
419				   CA_VSTREAM_POPEN_ARGV(argv->argv),
420				   CA_VSTREAM_POPEN_END)) == 0) {
421	    stat = -1;
422	} else {
423	    showq_client(mode, showq);
424	    stat = vstream_pclose(showq);
425	}
426	argv_free(argv);
427	myfree(showq_path);
428	if (stat != 0)
429	    msg_fatal_status(stat < 0 ? EX_OSERR : EX_SOFTWARE,
430			     "Error running %s", showq_path);
431    }
432
433    /*
434     * When the mail system is down, unprivileged users are stuck, because by
435     * design the mail system contains no set_uid programs. The only way for
436     * an unprivileged user to cross protection boundaries is to talk to the
437     * showq daemon.
438     */
439    else {
440	msg_fatal_status(EX_UNAVAILABLE,
441			 "Queue report unavailable - mail system is down"
442			 " (Connect to the %s %s service: %m)",
443			 var_mail_name, var_showq_service);
444    }
445}
446
447/* flush_queue - force delivery */
448
449static void flush_queue(void)
450{
451    const char *errstr;
452    uid_t   uid = getuid();
453
454    if (uid != 0 && uid != var_owner_uid
455	&& (errstr = check_user_acl_byuid(VAR_FLUSH_ACL, var_flush_acl,
456					  uid)) != 0)
457	msg_fatal_status(EX_NOPERM,
458		      "User %s(%ld) is not allowed to flush the mail queue",
459			 errstr, (long) uid);
460
461    /*
462     * Trigger the flush queue service.
463     */
464    if (mail_flush_deferred() < 0)
465	msg_fatal_status(EX_UNAVAILABLE,
466			 "Cannot flush mail queue - mail system is down");
467    if (mail_flush_maildrop() < 0)
468	msg_fatal_status(EX_UNAVAILABLE,
469			 "Cannot flush mail queue - mail system is down");
470    event_drain(2);
471}
472
473/* flush_site - flush mail for site */
474
475static void flush_site(const char *site)
476{
477    int     status;
478    const char *errstr;
479    uid_t   uid = getuid();
480
481    if (uid != 0 && uid != var_owner_uid
482	&& (errstr = check_user_acl_byuid(VAR_FLUSH_ACL, var_flush_acl,
483					  uid)) != 0)
484	msg_fatal_status(EX_NOPERM,
485		      "User %s(%ld) is not allowed to flush the mail queue",
486			 errstr, (long) uid);
487
488    flush_init();
489
490    switch (status = flush_send_site(site)) {
491    case FLUSH_STAT_OK:
492	exit(0);
493    case FLUSH_STAT_BAD:
494	msg_fatal_status(EX_USAGE, "Invalid request: \"%s\"", site);
495    case FLUSH_STAT_FAIL:
496	msg_fatal_status(EX_UNAVAILABLE,
497			 "Cannot flush mail queue - mail system is down");
498    case FLUSH_STAT_DENY:
499	msg_fatal_status(EX_UNAVAILABLE,
500		   "Flush service is not configured for destination \"%s\"",
501			 site);
502    default:
503	msg_fatal_status(EX_SOFTWARE,
504			 "Unknown flush server reply status %d", status);
505    }
506}
507
508/* flush_file - flush mail with specific queue ID */
509
510static void flush_file(const char *queue_id)
511{
512    int     status;
513    const char *errstr;
514    uid_t   uid = getuid();
515
516    if (uid != 0 && uid != var_owner_uid
517	&& (errstr = check_user_acl_byuid(VAR_FLUSH_ACL, var_flush_acl,
518					  uid)) != 0)
519	msg_fatal_status(EX_NOPERM,
520		      "User %s(%ld) is not allowed to flush the mail queue",
521			 errstr, (long) uid);
522
523    switch (status = flush_send_file(queue_id)) {
524    case FLUSH_STAT_OK:
525	exit(0);
526    case FLUSH_STAT_BAD:
527	msg_fatal_status(EX_USAGE, "Invalid request: \"%s\"", queue_id);
528    case FLUSH_STAT_FAIL:
529	msg_fatal_status(EX_UNAVAILABLE,
530			 "Cannot flush mail queue - mail system is down");
531    default:
532	msg_fatal_status(EX_SOFTWARE,
533			 "Unexpected flush server reply status %d", status);
534    }
535}
536
537/* unavailable - sanitize exit status from library run-time errors */
538
539static void unavailable(void)
540{
541    exit(EX_UNAVAILABLE);
542}
543
544/* usage - scream and die */
545
546static NORETURN usage(void)
547{
548    msg_fatal_status(EX_USAGE, "usage: postqueue -f | postqueue -i queueid | postqueue -j | postqueue -p | postqueue -s site");
549}
550
551MAIL_VERSION_STAMP_DECLARE;
552
553/* main - the main program */
554
555int     main(int argc, char **argv)
556{
557    struct stat st;
558    int     c;
559    int     fd;
560    int     mode = PQ_MODE_DEFAULT;
561    char   *site_to_flush = 0;
562    char   *id_to_flush = 0;
563    ARGV   *import_env;
564    int     bad_site;
565
566    /*
567     * Fingerprint executables and core dumps.
568     */
569    MAIL_VERSION_STAMP_ALLOCATE;
570
571    /*
572     * Be consistent with file permissions.
573     */
574    umask(022);
575
576    /*
577     * To minimize confusion, make sure that the standard file descriptors
578     * are open before opening anything else. XXX Work around for 44BSD where
579     * fstat can return EBADF on an open file descriptor.
580     */
581    for (fd = 0; fd < 3; fd++)
582	if (fstat(fd, &st) == -1
583	    && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
584	    msg_fatal_status(EX_UNAVAILABLE, "open /dev/null: %m");
585
586    /*
587     * Initialize. Set up logging. Read the global configuration file after
588     * parsing command-line arguments. Censor the process name: it is
589     * provided by the user.
590     */
591    argv[0] = "postqueue";
592    msg_vstream_init(argv[0], VSTREAM_ERR);
593    msg_cleanup(unavailable);
594    maillog_client_init(mail_task("postqueue"), MAILLOG_CLIENT_FLAG_NONE);
595    set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
596
597    /*
598     * Check the Postfix library version as soon as we enable logging.
599     */
600    MAIL_VERSION_CHECK;
601
602    /*
603     * Parse JCL. This program is set-gid and must sanitize all command-line
604     * parameters. The configuration directory argument is validated by the
605     * mail configuration read routine. Don't do complex things until we have
606     * completed initializations.
607     */
608    while ((c = GETOPT(argc, argv, "c:fi:jps:v")) > 0) {
609	switch (c) {
610	case 'c':				/* non-default configuration */
611	    if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
612		msg_fatal_status(EX_UNAVAILABLE, "out of memory");
613	    break;
614	case 'f':				/* flush queue */
615	    if (mode != PQ_MODE_DEFAULT)
616		usage();
617	    mode = PQ_MODE_FLUSH_QUEUE;
618	    break;
619	case 'i':				/* flush queue file */
620	    if (mode != PQ_MODE_DEFAULT)
621		usage();
622	    mode = PQ_MODE_FLUSH_FILE;
623	    id_to_flush = optarg;
624	    break;
625	case 'j':
626	    if (mode != PQ_MODE_DEFAULT)
627		usage();
628	    mode = PQ_MODE_JSON_LIST;
629	    break;
630	case 'p':				/* traditional mailq */
631	    if (mode != PQ_MODE_DEFAULT)
632		usage();
633	    mode = PQ_MODE_MAILQ_LIST;
634	    break;
635	case 's':				/* flush site */
636	    if (mode != PQ_MODE_DEFAULT)
637		usage();
638	    mode = PQ_MODE_FLUSH_SITE;
639	    site_to_flush = optarg;
640	    break;
641	case 'v':
642	    if (geteuid() == 0)
643		msg_verbose++;
644	    break;
645	default:
646	    usage();
647	}
648    }
649    if (argc > optind)
650	usage();
651
652    /*
653     * Further initialization...
654     */
655    mail_conf_read();
656    /* Re-evaluate mail_task() after reading main.cf. */
657    maillog_client_init(mail_task("postqueue"), MAILLOG_CLIENT_FLAG_NONE);
658    mail_dict_init();				/* proxy, sql, ldap */
659    get_mail_conf_str_table(str_table);
660
661    /*
662     * This program is designed to be set-gid, which makes it a potential
663     * target for attack. Strip and optionally override the process
664     * environment so that we don't have to trust the C library.
665     */
666    import_env = mail_parm_split(VAR_IMPORT_ENVIRON, var_import_environ);
667    clean_env(import_env->argv);
668    argv_free(import_env);
669
670    if (chdir(var_queue_dir))
671	msg_fatal_status(EX_UNAVAILABLE, "chdir %s: %m", var_queue_dir);
672
673    signal(SIGPIPE, SIG_IGN);
674
675    /* End of initializations. */
676
677    /*
678     * Further input validation.
679     */
680    if (site_to_flush != 0) {
681	bad_site = 0;
682	if (*site_to_flush == '[') {
683	    bad_site = !valid_mailhost_literal(site_to_flush, DONT_GRIPE);
684	} else {
685	    bad_site = !valid_hostname(site_to_flush, DONT_GRIPE);
686	}
687	if (bad_site)
688	    msg_fatal_status(EX_USAGE,
689	      "Cannot flush mail queue - invalid destination: \"%.100s%s\"",
690		   site_to_flush, strlen(site_to_flush) > 100 ? "..." : "");
691    }
692    if (id_to_flush != 0) {
693	if (!mail_queue_id_ok(id_to_flush))
694	    msg_fatal_status(EX_USAGE,
695		       "Cannot flush queue ID - invalid name: \"%.100s%s\"",
696		       id_to_flush, strlen(id_to_flush) > 100 ? "..." : "");
697    }
698
699    /*
700     * Start processing.
701     */
702    switch (mode) {
703    default:
704	msg_panic("unknown operation mode: %d", mode);
705	/* NOTREACHED */
706    case PQ_MODE_MAILQ_LIST:
707    case PQ_MODE_JSON_LIST:
708	show_queue(mode);
709	exit(0);
710	break;
711    case PQ_MODE_FLUSH_SITE:
712	flush_site(site_to_flush);
713	exit(0);
714	break;
715    case PQ_MODE_FLUSH_FILE:
716	flush_file(id_to_flush);
717	exit(0);
718	break;
719    case PQ_MODE_FLUSH_QUEUE:
720	flush_queue();
721	exit(0);
722	break;
723    case PQ_MODE_DEFAULT:
724	usage();
725	/* NOTREACHED */
726    }
727}
728