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