1 /* $NetBSD: postsuper.c,v 1.2 2017/02/14 01:16:47 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* postsuper 1 6 /* SUMMARY 7 /* Postfix superintendent 8 /* SYNOPSIS 9 /* .fi 10 /* \fBpostsuper\fR [\fB-psSv\fR] 11 /* [\fB-c \fIconfig_dir\fR] [\fB-d \fIqueue_id\fR] 12 /* [\fB-h \fIqueue_id\fR] [\fB-H \fIqueue_id\fR] 13 /* [\fB-r \fIqueue_id\fR] [\fIdirectory ...\fR] 14 /* DESCRIPTION 15 /* The \fBpostsuper\fR(1) command does maintenance jobs on the Postfix 16 /* queue. Use of the command is restricted to the superuser. 17 /* See the \fBpostqueue\fR(1) command for unprivileged queue operations 18 /* such as listing or flushing the mail queue. 19 /* 20 /* By default, \fBpostsuper\fR(1) performs the operations 21 /* requested with the 22 /* \fB-s\fR and \fB-p\fR command-line options on all Postfix queue 23 /* directories - this includes the \fBincoming\fR, \fBactive\fR and 24 /* \fBdeferred\fR directories with mail files and the \fBbounce\fR, 25 /* \fBdefer\fR, \fBtrace\fR and \fBflush\fR directories with log files. 26 /* 27 /* Options: 28 /* .IP "\fB-c \fIconfig_dir\fR" 29 /* The \fBmain.cf\fR configuration file is in the named directory 30 /* instead of the default configuration directory. See also the 31 /* MAIL_CONFIG environment setting below. 32 /* .IP "\fB-d \fIqueue_id\fR" 33 /* Delete one message with the named queue ID from the named 34 /* mail queue(s) (default: \fBhold\fR, \fBincoming\fR, \fBactive\fR and 35 /* \fBdeferred\fR). 36 /* 37 /* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads 38 /* queue IDs from standard input. For example, to delete all mail 39 /* with exactly one recipient \fBuser@example.com\fR: 40 /* .sp 41 /* .nf 42 /* mailq | tail +2 | grep -v '^ *(' | awk \'BEGIN { RS = "" } 43 /* # $7=sender, $8=recipient1, $9=recipient2 44 /* { if ($8 == "user@example.com" && $9 == "") 45 /* print $1 } 46 /* \' | tr -d '*!' | postsuper -d - 47 /* .fi 48 /* .sp 49 /* Specify "\fB-d ALL\fR" to remove all messages; for example, specify 50 /* "\fB-d ALL deferred\fR" to delete all mail in the \fBdeferred\fR queue. 51 /* As a safety measure, the word \fBALL\fR must be specified in upper 52 /* case. 53 /* .sp 54 /* Warning: Postfix queue IDs are reused (always with Postfix 55 /* <= 2.8; and with Postfix >= 2.9 when enable_long_queue_ids=no). 56 /* There is a very small possibility that postsuper deletes the 57 /* wrong message file when it is executed while the Postfix mail 58 /* system is delivering mail. 59 /* .sp 60 /* The scenario is as follows: 61 /* .RS 62 /* .IP 1) 63 /* The Postfix queue manager deletes the message that \fBpostsuper\fR(1) 64 /* is asked to delete, because Postfix is finished with the 65 /* message (it is delivered, or it is returned to the sender). 66 /* .IP 2) 67 /* New mail arrives, and the new message is given the same queue ID 68 /* as the message that \fBpostsuper\fR(1) is supposed to delete. 69 /* The probability for reusing a deleted queue ID is about 1 in 2**15 70 /* (the number of different microsecond values that the system clock 71 /* can distinguish within a second). 72 /* .IP 3) 73 /* \fBpostsuper\fR(1) deletes the new message, instead of the old 74 /* message that it should have deleted. 75 /* .RE 76 /* .IP "\fB-h \fIqueue_id\fR" 77 /* Put mail "on hold" so that no attempt is made to deliver it. 78 /* Move one message with the named queue ID from the named 79 /* mail queue(s) (default: \fBincoming\fR, \fBactive\fR and 80 /* \fBdeferred\fR) to the \fBhold\fR queue. 81 /* 82 /* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads 83 /* queue IDs from standard input. 84 /* .sp 85 /* Specify "\fB-h ALL\fR" to hold all messages; for example, specify 86 /* "\fB-h ALL deferred\fR" to hold all mail in the \fBdeferred\fR queue. 87 /* As a safety measure, the word \fBALL\fR must be specified in upper 88 /* case. 89 /* .sp 90 /* Note: while mail is "on hold" it will not expire when its 91 /* time in the queue exceeds the \fBmaximal_queue_lifetime\fR 92 /* or \fBbounce_queue_lifetime\fR setting. It becomes subject to 93 /* expiration after it is released from "hold". 94 /* .sp 95 /* This feature is available in Postfix 2.0 and later. 96 /* .IP "\fB-H \fIqueue_id\fR" 97 /* Release mail that was put "on hold". 98 /* Move one message with the named queue ID from the named 99 /* mail queue(s) (default: \fBhold\fR) to the \fBdeferred\fR queue. 100 /* 101 /* If a \fIqueue_id\fR of \fB-\fR is specified, the program reads 102 /* queue IDs from standard input. 103 /* .sp 104 /* Note: specify "\fBpostsuper -r\fR" to release mail that was kept on 105 /* hold for a significant fraction of \fB$maximal_queue_lifetime\fR 106 /* or \fB$bounce_queue_lifetime\fR, or longer. 107 /* .sp 108 /* Specify "\fB-H ALL\fR" to release all mail that is "on hold". 109 /* As a safety measure, the word \fBALL\fR must be specified in upper 110 /* case. 111 /* .sp 112 /* This feature is available in Postfix 2.0 and later. 113 /* .IP \fB-p\fR 114 /* Purge old temporary files that are left over after system or 115 /* software crashes. 116 /* .IP "\fB-r \fIqueue_id\fR" 117 /* Requeue the message with the named queue ID from the named 118 /* mail queue(s) (default: \fBhold\fR, \fBincoming\fR, \fBactive\fR and 119 /* \fBdeferred\fR). 120 /* To requeue multiple messages, specify multiple \fB-r\fR 121 /* command-line options. 122 /* 123 /* Alternatively, if a \fIqueue_id\fR of \fB-\fR is specified, 124 /* the program reads queue IDs from standard input. 125 /* .sp 126 /* Specify "\fB-r ALL\fR" to requeue all messages. As a safety 127 /* measure, the word \fBALL\fR must be specified in upper case. 128 /* .sp 129 /* A requeued message is moved to the \fBmaildrop\fR queue, 130 /* from where it is copied by the \fBpickup\fR(8) and 131 /* \fBcleanup\fR(8) daemons to a new queue file. In many 132 /* respects its handling differs from that of a new local 133 /* submission. 134 /* .RS 135 /* .IP \(bu 136 /* The message is not subjected to the smtpd_milters or 137 /* non_smtpd_milters settings. When mail has passed through 138 /* an external content filter, this would produce incorrect 139 /* results with Milter applications that depend on original 140 /* SMTP connection state information. 141 /* .IP \(bu 142 /* The message is subjected again to mail address rewriting 143 /* and substitution. This is useful when rewriting rules or 144 /* virtual mappings have changed. 145 /* .sp 146 /* The address rewriting context (local or remote) is the same 147 /* as when the message was received. 148 /* .IP \(bu 149 /* The message is subjected to the same content_filter settings 150 /* (if any) as used for new local mail submissions. This is 151 /* useful when content_filter settings have changed. 152 /* .RE 153 /* .IP 154 /* Warning: Postfix queue IDs are reused (always with Postfix 155 /* <= 2.8; and with Postfix >= 2.9 when enable_long_queue_ids=no). 156 /* There is a very small possibility that \fBpostsuper\fR(1) requeues 157 /* the wrong message file when it is executed while the Postfix mail 158 /* system is running, but no harm should be done. 159 /* .sp 160 /* This feature is available in Postfix 1.1 and later. 161 /* .IP \fB-s\fR 162 /* Structure check and structure repair. This should be done once 163 /* before Postfix startup. 164 /* .RS 165 /* .IP \(bu 166 /* Rename files whose name does not match the message file inode 167 /* number. This operation is necessary after restoring a mail 168 /* queue from a different machine or from backup, when queue 169 /* files were created with Postfix <= 2.8 or with 170 /* "enable_long_queue_ids = no". 171 /* .IP \(bu 172 /* Move queue files that are in the wrong place in the file system 173 /* hierarchy and remove subdirectories that are no longer needed. 174 /* File position rearrangements are necessary after a change in the 175 /* \fBhash_queue_names\fR and/or \fBhash_queue_depth\fR 176 /* configuration parameters. 177 /* .IP \(bu 178 /* Rename queue files created with "enable_long_queue_ids = 179 /* yes" to short names, for migration to Postfix <= 2.8. The 180 /* procedure is as follows: 181 /* .sp 182 /* .nf 183 /* .na 184 /* # postfix stop 185 /* # postconf enable_long_queue_ids=no 186 /* # postsuper 187 /* .ad 188 /* .fi 189 /* .sp 190 /* Run \fBpostsuper\fR(1) repeatedly until it stops reporting 191 /* file name changes. 192 /* .RE 193 /* .IP \fB-S\fR 194 /* A redundant version of \fB-s\fR that requires that long 195 /* file names also match the message file inode number. This 196 /* option exists for testing purposes, and is available with 197 /* Postfix 2.9 and later. 198 /* .IP \fB-v\fR 199 /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR 200 /* options make the software increasingly verbose. 201 /* DIAGNOSTICS 202 /* Problems are reported to the standard error stream and to 203 /* \fBsyslogd\fR(8). 204 /* 205 /* \fBpostsuper\fR(1) reports the number of messages deleted with \fB-d\fR, 206 /* the number of messages requeued with \fB-r\fR, and the number of 207 /* messages whose queue file name was fixed with \fB-s\fR. The report 208 /* is written to the standard error stream and to \fBsyslogd\fR(8). 209 /* ENVIRONMENT 210 /* .ad 211 /* .fi 212 /* .IP MAIL_CONFIG 213 /* Directory with the \fBmain.cf\fR file. 214 /* BUGS 215 /* Mail that is not sanitized by Postfix (i.e. mail in the \fBmaildrop\fR 216 /* queue) cannot be placed "on hold". 217 /* CONFIGURATION PARAMETERS 218 /* .ad 219 /* .fi 220 /* The following \fBmain.cf\fR parameters are especially relevant to 221 /* this program. 222 /* The text below provides only a parameter summary. See 223 /* \fBpostconf\fR(5) for more details including examples. 224 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" 225 /* The default location of the Postfix main.cf and master.cf 226 /* configuration files. 227 /* .IP "\fBhash_queue_depth (1)\fR" 228 /* The number of subdirectory levels for queue directories listed with 229 /* the hash_queue_names parameter. 230 /* .IP "\fBhash_queue_names (deferred, defer)\fR" 231 /* The names of queue directories that are split across multiple 232 /* subdirectory levels. 233 /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" 234 /* The location of the Postfix top-level queue directory. 235 /* .IP "\fBsyslog_facility (mail)\fR" 236 /* The syslog facility of Postfix logging. 237 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" 238 /* The mail system name that is prepended to the process name in syslog 239 /* records, so that "smtpd" becomes, for example, "postfix/smtpd". 240 /* .PP 241 /* Available in Postfix version 2.9 and later: 242 /* .IP "\fBenable_long_queue_ids (no)\fR" 243 /* Enable long, non-repeating, queue IDs (queue file names). 244 /* SEE ALSO 245 /* sendmail(1), Sendmail-compatible user interface 246 /* postqueue(1), unprivileged queue operations 247 /* LICENSE 248 /* .ad 249 /* .fi 250 /* The Secure Mailer license must be distributed with this software. 251 /* AUTHOR(S) 252 /* Wietse Venema 253 /* IBM T.J. Watson Research 254 /* P.O. Box 704 255 /* Yorktown Heights, NY 10598, USA 256 /* 257 /* Wietse Venema 258 /* Google, Inc. 259 /* 111 8th Avenue 260 /* New York, NY 10011, USA 261 /*--*/ 262 263 /* System library. */ 264 265 #include <sys_defs.h> 266 #include <sys/stat.h> 267 #include <unistd.h> 268 #include <stdlib.h> 269 #include <errno.h> 270 #include <string.h> 271 #include <signal.h> 272 #include <stdio.h> /* remove() */ 273 #include <utime.h> 274 275 /* Utility library. */ 276 277 #include <mymalloc.h> 278 #include <msg.h> 279 #include <msg_syslog.h> 280 #include <vstream.h> 281 #include <msg_vstream.h> 282 #include <scan_dir.h> 283 #include <vstring.h> 284 #include <safe.h> 285 #include <set_ugid.h> 286 #include <argv.h> 287 #include <vstring_vstream.h> 288 #include <sane_fsops.h> 289 #include <myrand.h> 290 #include <warn_stat.h> 291 292 /* Global library. */ 293 294 #include <mail_task.h> 295 #include <mail_conf.h> 296 #include <mail_params.h> 297 #include <mail_version.h> 298 #define MAIL_QUEUE_INTERNAL 299 #include <mail_queue.h> 300 #include <mail_open_ok.h> 301 #include <file_id.h> 302 303 /* Application-specific. */ 304 305 #define MAX_TEMP_AGE (60 * 60 * 24) /* temp file maximal age */ 306 #define STR vstring_str /* silly little macro */ 307 308 #define ACTION_STRUCT (1<<0) /* fix file organization */ 309 #define ACTION_PURGE (1<<1) /* purge old temp files */ 310 #define ACTION_DELETE_ONE (1<<2) /* delete named queue file(s) */ 311 #define ACTION_DELETE_ALL (1<<3) /* delete all queue file(s) */ 312 #define ACTION_REQUEUE_ONE (1<<4) /* requeue named queue file(s) */ 313 #define ACTION_REQUEUE_ALL (1<<5) /* requeue all queue file(s) */ 314 #define ACTION_HOLD_ONE (1<<6) /* put named queue file(s) on hold */ 315 #define ACTION_HOLD_ALL (1<<7) /* put all messages on hold */ 316 #define ACTION_RELEASE_ONE (1<<8) /* release named queue file(s) */ 317 #define ACTION_RELEASE_ALL (1<<9) /* release all "on hold" mail */ 318 #define ACTION_STRUCT_RED (1<<10) /* fix long queue ID inode fields */ 319 320 #define ACTION_DEFAULT (ACTION_STRUCT | ACTION_PURGE) 321 322 /* 323 * Actions that operate on individually named queue files. These must never 324 * be done when queue file names are changed to match their inode number. 325 */ 326 #define ACTIONS_BY_QUEUE_ID (ACTION_DELETE_ONE | ACTION_REQUEUE_ONE \ 327 | ACTION_HOLD_ONE | ACTION_RELEASE_ONE) 328 329 /* 330 * Mass rename operations that are postponed to a second pass after queue 331 * file names are changed to match their inode number. 332 */ 333 #define ACTIONS_AFTER_INUM_FIX (ACTION_REQUEUE_ALL | ACTION_HOLD_ALL \ 334 | ACTION_RELEASE_ALL) 335 336 /* 337 * Information about queue directories and what we expect to do there. If a 338 * file has unexpected owner permissions and is older than some threshold, 339 * the file is discarded. We don't step into maildrop subdirectories - if 340 * maildrop is writable, we might end up in the wrong place, deleting the 341 * wrong information. 342 */ 343 struct queue_info { 344 char *name; /* directory name */ 345 int perms; /* expected permissions */ 346 int flags; /* see below */ 347 }; 348 349 #define RECURSE (1<<0) /* step into subdirectories */ 350 #define DONT_RECURSE 0 /* don't step into directories */ 351 352 static struct queue_info queue_info[] = { 353 MAIL_QUEUE_MAILDROP, MAIL_QUEUE_STAT_READY, DONT_RECURSE, 354 MAIL_QUEUE_INCOMING, MAIL_QUEUE_STAT_READY, RECURSE, 355 MAIL_QUEUE_ACTIVE, MAIL_QUEUE_STAT_READY, RECURSE, 356 MAIL_QUEUE_DEFERRED, MAIL_QUEUE_STAT_READY, RECURSE, 357 MAIL_QUEUE_HOLD, MAIL_QUEUE_STAT_READY, RECURSE, 358 MAIL_QUEUE_TRACE, 0600, RECURSE, 359 MAIL_QUEUE_DEFER, 0600, RECURSE, 360 MAIL_QUEUE_BOUNCE, 0600, RECURSE, 361 MAIL_QUEUE_FLUSH, 0600, RECURSE, 362 0, 363 }; 364 365 /* 366 * Directories with per-message meta files. 367 */ 368 const char *log_queue_names[] = { 369 MAIL_QUEUE_BOUNCE, 370 MAIL_QUEUE_DEFER, 371 MAIL_QUEUE_TRACE, 372 0, 373 }; 374 375 /* 376 * Cruft that we append to a file name when a queue ID is named after the 377 * message file inode number. This cruft must not pass mail_queue_id_ok() so 378 * that the queue manager will ignore it, should people be so unwise as to 379 * run this operation on a live mail system. 380 */ 381 #define SUFFIX "#FIX" 382 #define SUFFIX_LEN 4 383 384 /* 385 * Grr. These counters are global, because C only has clumsy ways to return 386 * multiple results from a function. 387 */ 388 static int message_requeued = 0; /* requeued messages */ 389 static int message_held = 0; /* messages put on hold */ 390 static int message_released = 0; /* messages released from hold */ 391 static int message_deleted = 0; /* deleted messages */ 392 static int inode_fixed = 0; /* queue id matched to inode number */ 393 static int inode_mismatch = 0; /* queue id inode mismatch */ 394 static int position_mismatch = 0; /* file position mismatch */ 395 396 /* 397 * Silly little macros. These translate arcane expressions into something 398 * more at a conceptual level. 399 */ 400 #define MESSAGE_QUEUE(qp) ((qp)->perms == MAIL_QUEUE_STAT_READY) 401 #define READY_MESSAGE(st) (((st).st_mode & S_IRWXU) == MAIL_QUEUE_STAT_READY) 402 403 /* find_queue_info - look up expected permissions field by queue name */ 404 405 static struct queue_info *find_queue_info(const char *queue_name) 406 { 407 struct queue_info *qp; 408 409 for (qp = queue_info; qp->name; qp++) 410 if (strcmp(queue_name, qp->name) == 0) 411 return (qp); 412 msg_fatal("invalid directory name: %s", queue_name); 413 } 414 415 /* postremove - remove file with extreme prejudice */ 416 417 static int postremove(const char *path) 418 { 419 int ret; 420 421 if ((ret = remove(path)) < 0) { 422 if (errno != ENOENT) 423 msg_fatal("remove file %s: %m", path); 424 } else { 425 if (msg_verbose) 426 msg_info("removed file %s", path); 427 } 428 return (ret); 429 } 430 431 /* postrename - rename file with extreme prejudice */ 432 433 static int postrename(const char *old, const char *new) 434 { 435 int ret; 436 437 if ((ret = sane_rename(old, new)) < 0) { 438 if (errno != ENOENT 439 || mail_queue_mkdirs(new) < 0 440 || (ret = sane_rename(old, new)) < 0) 441 if (errno != ENOENT) 442 msg_fatal("rename file %s as %s: %m", old, new); 443 } else { 444 if (msg_verbose) 445 msg_info("renamed file %s as %s", old, new); 446 } 447 return (ret); 448 } 449 450 /* postrmdir - remove directory with extreme prejudice */ 451 452 static int postrmdir(const char *path) 453 { 454 int ret; 455 456 if ((ret = rmdir(path)) < 0) { 457 if (errno != ENOENT) 458 msg_fatal("remove directory %s: %m", path); 459 } else { 460 if (msg_verbose) 461 msg_info("remove directory %s", path); 462 } 463 return (ret); 464 } 465 466 /* delete_one - delete one message instance and all its associated files */ 467 468 static int delete_one(const char **queue_names, const char *queue_id) 469 { 470 struct stat st; 471 const char **msg_qpp; 472 const char **log_qpp; 473 const char *msg_path; 474 VSTRING *log_path_buf; 475 int found; 476 int tries; 477 478 /* 479 * Sanity check. No early returns beyond this point. 480 */ 481 if (!mail_queue_id_ok(queue_id)) { 482 msg_warn("invalid mail queue id: %s", queue_id); 483 return (0); 484 } 485 log_path_buf = vstring_alloc(100); 486 487 /* 488 * Skip meta file directories. Delete trace/defer/bounce logfiles before 489 * deleting the corresponding message file, and only if the message file 490 * exists. This minimizes but does not eliminate a race condition with 491 * queue ID reuse which results in deleting the wrong files. 492 */ 493 for (found = 0, tries = 0; found == 0 && tries < 2; tries++) { 494 for (msg_qpp = queue_names; *msg_qpp != 0; msg_qpp++) { 495 if (!MESSAGE_QUEUE(find_queue_info(*msg_qpp))) 496 continue; 497 if (mail_open_ok(*msg_qpp, queue_id, &st, &msg_path) != MAIL_OPEN_YES) 498 continue; 499 for (log_qpp = log_queue_names; *log_qpp != 0; log_qpp++) 500 postremove(mail_queue_path(log_path_buf, *log_qpp, queue_id)); 501 if (postremove(msg_path) == 0) { 502 found = 1; 503 msg_info("%s: removed", queue_id); 504 break; 505 } /* else: maybe lost a race */ 506 } 507 } 508 vstring_free(log_path_buf); 509 return (found); 510 } 511 512 /* requeue_one - requeue one message instance and delete its logfiles */ 513 514 static int requeue_one(const char **queue_names, const char *queue_id) 515 { 516 struct stat st; 517 const char **msg_qpp; 518 const char *old_path; 519 VSTRING *new_path_buf; 520 int found; 521 int tries; 522 struct utimbuf tbuf; 523 524 /* 525 * Sanity check. No early returns beyond this point. 526 */ 527 if (!mail_queue_id_ok(queue_id)) { 528 msg_warn("invalid mail queue id: %s", queue_id); 529 return (0); 530 } 531 new_path_buf = vstring_alloc(100); 532 533 /* 534 * Skip meta file directories. Like the mass requeue operation, we not 535 * delete defer or bounce logfiles, to avoid losing a race where the 536 * queue manager decides to bounce mail after all recipients have been 537 * tried. 538 */ 539 for (found = 0, tries = 0; found == 0 && tries < 2; tries++) { 540 for (msg_qpp = queue_names; *msg_qpp != 0; msg_qpp++) { 541 if (strcmp(*msg_qpp, MAIL_QUEUE_MAILDROP) == 0) 542 continue; 543 if (!MESSAGE_QUEUE(find_queue_info(*msg_qpp))) 544 continue; 545 if (mail_open_ok(*msg_qpp, queue_id, &st, &old_path) != MAIL_OPEN_YES) 546 continue; 547 (void) mail_queue_path(new_path_buf, MAIL_QUEUE_MAILDROP, queue_id); 548 if (postrename(old_path, STR(new_path_buf)) == 0) { 549 tbuf.actime = tbuf.modtime = time((time_t *) 0); 550 if (utime(STR(new_path_buf), &tbuf) < 0) 551 msg_warn("%s: reset time stamps: %m", STR(new_path_buf)); 552 msg_info("%s: requeued", queue_id); 553 found = 1; 554 break; 555 } /* else: maybe lost a race */ 556 } 557 } 558 vstring_free(new_path_buf); 559 return (found); 560 } 561 562 /* hold_one - put "on hold" one message instance */ 563 564 static int hold_one(const char **queue_names, const char *queue_id) 565 { 566 struct stat st; 567 const char **msg_qpp; 568 const char *old_path; 569 VSTRING *new_path_buf; 570 int found; 571 int tries; 572 573 /* 574 * Sanity check. No early returns beyond this point. 575 */ 576 if (!mail_queue_id_ok(queue_id)) { 577 msg_warn("invalid mail queue id: %s", queue_id); 578 return (0); 579 } 580 new_path_buf = vstring_alloc(100); 581 582 /* 583 * Skip meta file directories. Like the mass requeue operation, we not 584 * delete defer or bounce logfiles, to avoid losing a race where the 585 * queue manager decides to bounce mail after all recipients have been 586 * tried. 587 * 588 * XXX We must not put maildrop mail on hold because that would mix already 589 * sanitized mail with mail that still needs to be sanitized. 590 */ 591 for (found = 0, tries = 0; found == 0 && tries < 2; tries++) { 592 for (msg_qpp = queue_names; *msg_qpp != 0; msg_qpp++) { 593 if (strcmp(*msg_qpp, MAIL_QUEUE_MAILDROP) == 0) 594 continue; 595 if (strcmp(*msg_qpp, MAIL_QUEUE_HOLD) == 0) 596 continue; 597 if (!MESSAGE_QUEUE(find_queue_info(*msg_qpp))) 598 continue; 599 if (mail_open_ok(*msg_qpp, queue_id, &st, &old_path) != MAIL_OPEN_YES) 600 continue; 601 (void) mail_queue_path(new_path_buf, MAIL_QUEUE_HOLD, queue_id); 602 if (postrename(old_path, STR(new_path_buf)) == 0) { 603 msg_info("%s: placed on hold", queue_id); 604 found = 1; 605 break; 606 } /* else: maybe lost a race */ 607 } 608 } 609 vstring_free(new_path_buf); 610 return (found); 611 } 612 613 /* release_one - release one message instance that was placed "on hold" */ 614 615 static int release_one(const char **queue_names, const char *queue_id) 616 { 617 struct stat st; 618 const char **msg_qpp; 619 const char *old_path; 620 VSTRING *new_path_buf; 621 int found; 622 623 /* 624 * Sanity check. No early returns beyond this point. 625 */ 626 if (!mail_queue_id_ok(queue_id)) { 627 msg_warn("invalid mail queue id: %s", queue_id); 628 return (0); 629 } 630 new_path_buf = vstring_alloc(100); 631 632 /* 633 * Skip inapplicable directories. This can happen when -H is combined 634 * with other operations. 635 */ 636 found = 0; 637 for (msg_qpp = queue_names; *msg_qpp != 0; msg_qpp++) { 638 if (strcmp(*msg_qpp, MAIL_QUEUE_HOLD) != 0) 639 continue; 640 if (mail_open_ok(*msg_qpp, queue_id, &st, &old_path) != MAIL_OPEN_YES) 641 continue; 642 (void) mail_queue_path(new_path_buf, MAIL_QUEUE_DEFERRED, queue_id); 643 if (postrename(old_path, STR(new_path_buf)) == 0) { 644 msg_info("%s: released from hold", queue_id); 645 found = 1; 646 break; 647 } 648 } 649 vstring_free(new_path_buf); 650 return (found); 651 } 652 653 /* operate_stream - operate on queue IDs given on stream */ 654 655 static int operate_stream(VSTREAM *fp, 656 int (*operator) (const char **, const char *), 657 const char **queues) 658 { 659 VSTRING *buf = vstring_alloc(20); 660 int found = 0; 661 662 while (vstring_get_nonl(buf, fp) != VSTREAM_EOF) 663 found += operator(queues, STR(buf)); 664 665 vstring_free(buf); 666 return (found); 667 } 668 669 /* fix_queue_id - make message queue ID match inode number */ 670 671 static int fix_queue_id(const char *actual_path, const char *actual_queue, 672 const char *actual_id, struct stat * st) 673 { 674 VSTRING *old_path = vstring_alloc(10); 675 VSTRING *new_path = vstring_alloc(10); 676 VSTRING *new_id = vstring_alloc(10); 677 const char **log_qpp; 678 char *cp; 679 int ret; 680 681 /* 682 * Create the new queue ID from the existing time digits and from the new 683 * inode number. Since we are renaming multiple files, the new name must 684 * be deterministic so that we can recover even when the renaming 685 * operation is interrupted in the middle. 686 */ 687 if (MQID_FIND_LG_INUM_SEPARATOR(cp, actual_id) == 0) { 688 /* Short->short queue ID. Replace the inode portion. */ 689 vstring_sprintf(new_id, "%.*s%s", 690 MQID_SH_USEC_PAD, actual_id, 691 get_file_id_st(st, 0)); 692 } else if (var_long_queue_ids) { 693 /* Long->long queue ID. Replace the inode portion. */ 694 vstring_sprintf(new_id, "%.*s%c%s", 695 (int) (cp - actual_id), actual_id, MQID_LG_INUM_SEP, 696 get_file_id_st(st, 1)); 697 } else { 698 /* Long->short queue ID. Reformat time and replace inode portion. */ 699 MQID_LG_GET_HEX_USEC(new_id, cp); 700 vstring_strcat(new_id, get_file_id_st(st, 0)); 701 } 702 703 /* 704 * Rename logfiles before renaming the message file, so that we can 705 * recover when a previous attempt was interrupted. 706 */ 707 for (log_qpp = log_queue_names; *log_qpp; log_qpp++) { 708 mail_queue_path(old_path, *log_qpp, actual_id); 709 mail_queue_path(new_path, *log_qpp, STR(new_id)); 710 vstring_strcat(new_path, SUFFIX); 711 postrename(STR(old_path), STR(new_path)); 712 } 713 714 /* 715 * Rename the message file last, so that we know that we are done with 716 * this message and with all its logfiles. 717 */ 718 mail_queue_path(new_path, actual_queue, STR(new_id)); 719 vstring_strcat(new_path, SUFFIX); 720 ret = postrename(actual_path, STR(new_path)); 721 722 /* 723 * Clean up. 724 */ 725 vstring_free(old_path); 726 vstring_free(new_path); 727 vstring_free(new_id); 728 729 return (ret); 730 } 731 732 /* super - check queue structure, clean up, do wild-card operations */ 733 734 static void super(const char **queues, int action) 735 { 736 ARGV *hash_queue_names = argv_split(var_hash_queue_names, CHARS_COMMA_SP); 737 VSTRING *actual_path = vstring_alloc(10); 738 VSTRING *wanted_path = vstring_alloc(10); 739 struct stat st; 740 const char *queue_name; 741 SCAN_DIR *info; 742 char *path; 743 int actual_depth; 744 int wanted_depth; 745 char **cpp; 746 struct queue_info *qp; 747 unsigned long inum; 748 int long_name; 749 int error; 750 751 /* 752 * Make sure every file is in the right place, clean out stale files, and 753 * remove non-file/non-directory objects. 754 */ 755 while ((queue_name = *queues++) != 0) { 756 757 if (msg_verbose) 758 msg_info("queue: %s", queue_name); 759 760 /* 761 * Look up queue-specific properties: desired hashing depth, what 762 * file permissions to look for, and whether or not it is desirable 763 * to step into subdirectories. 764 */ 765 qp = find_queue_info(queue_name); 766 for (cpp = hash_queue_names->argv; /* void */ ; cpp++) { 767 if (*cpp == 0) { 768 wanted_depth = 0; 769 break; 770 } 771 if (strcmp(*cpp, queue_name) == 0) { 772 wanted_depth = var_hash_queue_depth; 773 break; 774 } 775 } 776 777 /* 778 * Sanity check. Some queues just cannot be recursive. 779 */ 780 if (wanted_depth > 0 && (qp->flags & RECURSE) == 0) 781 msg_fatal("%s queue must not be hashed", queue_name); 782 783 /* 784 * Other per-directory initialization. 785 */ 786 info = scan_dir_open(queue_name); 787 actual_depth = 0; 788 789 for (;;) { 790 791 /* 792 * If we reach the end of a subdirectory, return to its parent. 793 * Delete subdirectories that are no longer needed. 794 */ 795 if ((path = scan_dir_next(info)) == 0) { 796 if (actual_depth == 0) 797 break; 798 if (actual_depth > wanted_depth) 799 postrmdir(scan_dir_path(info)); 800 scan_dir_pop(info); 801 actual_depth--; 802 continue; 803 } 804 805 /* 806 * If we stumble upon a subdirectory, enter it, if it is 807 * considered safe to do so. Otherwise, try to remove the 808 * subdirectory at a later stage. 809 */ 810 if (strlen(path) == 1 && (qp->flags & RECURSE) != 0) { 811 actual_depth++; 812 scan_dir_push(info, path); 813 continue; 814 } 815 816 /* 817 * From here on we need to keep track of operations that 818 * invalidate or revalidate the actual_path and path variables, 819 * otherwise we can hit the wrong files. 820 */ 821 vstring_sprintf(actual_path, "%s/%s", scan_dir_path(info), path); 822 if (stat(STR(actual_path), &st) < 0) 823 continue; 824 825 /* 826 * Remove alien directories. If maildrop is compromised, then we 827 * cannot abort just because we cannot remove someone's 828 * directory. 829 */ 830 if (S_ISDIR(st.st_mode)) { 831 if (rmdir(STR(actual_path)) < 0) { 832 if (errno != ENOENT) 833 msg_warn("remove subdirectory %s: %m", STR(actual_path)); 834 } else { 835 if (msg_verbose) 836 msg_info("remove subdirectory %s", STR(actual_path)); 837 } 838 /* No further work on this object is possible. */ 839 continue; 840 } 841 842 /* 843 * Mass deletion. We count the deletion of mail that this system 844 * has taken responsibility for. XXX This option does not use 845 * mail_queue_remove(), so that it can avoid having to first move 846 * queue files to the "right" subdirectory level. 847 */ 848 if (action & ACTION_DELETE_ALL) { 849 if (postremove(STR(actual_path)) == 0) 850 if (MESSAGE_QUEUE(qp) && READY_MESSAGE(st)) 851 message_deleted++; 852 /* No further work on this object is possible. */ 853 continue; 854 } 855 856 /* 857 * Remove non-file objects and old temporary files. Be careful 858 * not to delete bounce or defer logs just because they are more 859 * than a couple days old. 860 */ 861 if (!S_ISREG(st.st_mode) 862 || ((action & ACTION_PURGE) != 0 863 && MESSAGE_QUEUE(qp) 864 && !READY_MESSAGE(st) 865 && time((time_t *) 0) > st.st_mtime + MAX_TEMP_AGE)) { 866 (void) postremove(STR(actual_path)); 867 /* No further work on this object is possible. */ 868 continue; 869 } 870 871 /* 872 * Fix queueid#FIX names that were left from a previous pass over 873 * the queue where message queue file names were matched to their 874 * inode number. We strip the suffix and move the file into the 875 * proper subdirectory level. Make sure that the name minus 876 * suffix is well formed and that the name matches the file inode 877 * number. 878 */ 879 if ((action & ACTION_STRUCT) 880 && strcmp(path + (strlen(path) - SUFFIX_LEN), SUFFIX) == 0) { 881 path[strlen(path) - SUFFIX_LEN] = 0; /* XXX */ 882 if (!mail_queue_id_ok(path)) { 883 msg_warn("bogus file name: %s", STR(actual_path)); 884 continue; 885 } 886 if (MESSAGE_QUEUE(qp)) { 887 MQID_GET_INUM(path, inum, long_name, error); 888 if (error) { 889 msg_warn("bogus file name: %s", STR(actual_path)); 890 continue; 891 } 892 if (inum != (unsigned long) st.st_ino) { 893 msg_warn("name/inode mismatch: %s", STR(actual_path)); 894 continue; 895 } 896 } 897 (void) mail_queue_path(wanted_path, queue_name, path); 898 if (postrename(STR(actual_path), STR(wanted_path)) < 0) { 899 /* No further work on this object is possible. */ 900 continue; 901 } else { 902 if (MESSAGE_QUEUE(qp)) 903 inode_fixed++; 904 vstring_strcpy(actual_path, STR(wanted_path)); 905 /* At this point, path and actual_path are revalidated. */ 906 } 907 } 908 909 /* 910 * Skip over files with illegal names. The library routines 911 * refuse to operate on them. 912 */ 913 if (!mail_queue_id_ok(path)) { 914 msg_warn("bogus file name: %s", STR(actual_path)); 915 continue; 916 } 917 918 /* 919 * See if the file name matches the file inode number. Skip meta 920 * file directories. This option requires that meta files be put 921 * into their proper place before queue files, so that we can 922 * rename queue files and meta files at the same time. Mis-named 923 * files are renamed to newqueueid#FIX on the first pass, and 924 * upon the second pass the #FIX is stripped off the name. Of 925 * course we have to be prepared that the program is interrupted 926 * before it completes, so any left-over newqueueid#FIX files 927 * have to be handled properly. XXX This option cannot use 928 * mail_queue_rename(), because the queue file name violates 929 * normal queue file syntax. 930 * 931 * By design there is no need to "fix" non-repeating names. What 932 * follows is applicable only when reverting from long names to 933 * short names, or when migrating short names from one queue to 934 * another. 935 */ 936 if ((action & ACTION_STRUCT) != 0 && MESSAGE_QUEUE(qp)) { 937 MQID_GET_INUM(path, inum, long_name, error); 938 if (error) { 939 msg_warn("bogus file name: %s", STR(actual_path)); 940 continue; 941 } 942 if ((long_name != 0 && var_long_queue_ids == 0) 943 || (inum != (unsigned long) st.st_ino 944 && (long_name == 0 || (action & ACTION_STRUCT_RED)))) { 945 inode_mismatch++; /* before we fix */ 946 action &= ~ACTIONS_AFTER_INUM_FIX; 947 fix_queue_id(STR(actual_path), queue_name, path, &st); 948 /* At this point, path and actual_path are invalidated. */ 949 continue; 950 } 951 } 952 953 /* 954 * Mass requeuing. The pickup daemon will copy requeued mail to a 955 * new queue file, so that address rewriting is applied again. 956 * XXX This option does not use mail_queue_rename(), so that it 957 * can avoid having to first move queue files to the "right" 958 * subdirectory level. Like the requeue_one() routine, this code 959 * does not touch logfiles. 960 */ 961 if ((action & ACTION_REQUEUE_ALL) 962 && MESSAGE_QUEUE(qp) 963 && strcmp(queue_name, MAIL_QUEUE_MAILDROP) != 0) { 964 (void) mail_queue_path(wanted_path, MAIL_QUEUE_MAILDROP, path); 965 if (postrename(STR(actual_path), STR(wanted_path)) == 0) 966 message_requeued++; 967 /* At this point, path and actual_path are invalidated. */ 968 continue; 969 } 970 971 /* 972 * Mass renaming to the "on hold" queue. XXX This option does not 973 * use mail_queue_rename(), so that it can avoid having to first 974 * move queue files to the "right" subdirectory level. Like the 975 * hold_one() routine, this code does not touch logfiles, and 976 * must not touch files in the maildrop queue, because maildrop 977 * files contain data that has not yet been sanitized and 978 * therefore must not be mixed with already sanitized mail. 979 */ 980 if ((action & ACTION_HOLD_ALL) 981 && MESSAGE_QUEUE(qp) 982 && strcmp(queue_name, MAIL_QUEUE_MAILDROP) != 0 983 && strcmp(queue_name, MAIL_QUEUE_HOLD) != 0) { 984 (void) mail_queue_path(wanted_path, MAIL_QUEUE_HOLD, path); 985 if (postrename(STR(actual_path), STR(wanted_path)) == 0) 986 message_held++; 987 /* At this point, path and actual_path are invalidated. */ 988 continue; 989 } 990 991 /* 992 * Mass release from the "on hold" queue. XXX This option does 993 * not use mail_queue_rename(), so that it can avoid having to 994 * first move queue files to the "right" subdirectory level. Like 995 * the release_one() routine, this code must not touch logfiles. 996 */ 997 if ((action & ACTION_RELEASE_ALL) 998 && strcmp(queue_name, MAIL_QUEUE_HOLD) == 0) { 999 (void) mail_queue_path(wanted_path, MAIL_QUEUE_DEFERRED, path); 1000 if (postrename(STR(actual_path), STR(wanted_path)) == 0) 1001 message_released++; 1002 /* At this point, path and actual_path are invalidated. */ 1003 continue; 1004 } 1005 1006 /* 1007 * See if this file sits in the right place in the file system 1008 * hierarchy. Its place may be wrong after a change to the 1009 * hash_queue_{names,depth} parameter settings. This requires 1010 * that the bounce/defer logfiles be at the right subdirectory 1011 * level first, otherwise we would fail to properly rename 1012 * bounce/defer logfiles. 1013 */ 1014 if (action & ACTION_STRUCT) { 1015 (void) mail_queue_path(wanted_path, queue_name, path); 1016 if (strcmp(STR(actual_path), STR(wanted_path)) != 0) { 1017 position_mismatch++; /* before we fix */ 1018 (void) postrename(STR(actual_path), STR(wanted_path)); 1019 /* At this point, path and actual_path are invalidated. */ 1020 continue; 1021 } 1022 } 1023 } 1024 scan_dir_close(info); 1025 } 1026 1027 /* 1028 * Clean up. 1029 */ 1030 vstring_free(wanted_path); 1031 vstring_free(actual_path); 1032 argv_free(hash_queue_names); 1033 } 1034 1035 /* interrupted - signal handler */ 1036 1037 static void interrupted(int sig) 1038 { 1039 1040 /* 1041 * This commands requires root privileges. We therefore do not worry 1042 * about hostile signals, and report problems via msg_warn(). 1043 * 1044 * We use the in-kernel SIGINT handler address as an atomic variable to 1045 * prevent nested interrupted() calls. For this reason, main() must 1046 * configure interrupted() as SIGINT handler before other signal handlers 1047 * are allowed to invoke interrupted(). See also similar code in 1048 * postdrop. 1049 */ 1050 if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 1051 (void) signal(SIGQUIT, SIG_IGN); 1052 (void) signal(SIGTERM, SIG_IGN); 1053 (void) signal(SIGHUP, SIG_IGN); 1054 if (inode_mismatch > 0 || inode_fixed > 0 || position_mismatch > 0) 1055 msg_warn("OPERATION INCOMPLETE -- RERUN COMMAND TO FIX THE QUEUE FIRST"); 1056 if (sig) 1057 _exit(sig); 1058 } 1059 } 1060 1061 /* fatal_warning - print warning if queue fix is incomplete */ 1062 1063 static void fatal_warning(void) 1064 { 1065 interrupted(0); 1066 } 1067 1068 MAIL_VERSION_STAMP_DECLARE; 1069 1070 int main(int argc, char **argv) 1071 { 1072 int fd; 1073 struct stat st; 1074 char *slash; 1075 int action = 0; 1076 const char **queues; 1077 int c; 1078 ARGV *requeue_names = 0; 1079 ARGV *delete_names = 0; 1080 ARGV *hold_names = 0; 1081 ARGV *release_names = 0; 1082 char **cpp; 1083 1084 /* 1085 * Defaults. The structural checks must fix the directory levels of "log 1086 * file" directories (bounce, defer) before doing structural checks on 1087 * the "message file" directories, so that we can find the logfiles in 1088 * the right place when message files need to be renamed to match their 1089 * inode number. 1090 */ 1091 static char *default_queues[] = { 1092 MAIL_QUEUE_DEFER, /* before message directories */ 1093 MAIL_QUEUE_BOUNCE, /* before message directories */ 1094 MAIL_QUEUE_MAILDROP, 1095 MAIL_QUEUE_INCOMING, 1096 MAIL_QUEUE_ACTIVE, 1097 MAIL_QUEUE_DEFERRED, 1098 MAIL_QUEUE_HOLD, 1099 MAIL_QUEUE_FLUSH, 1100 0, 1101 }; 1102 static char *default_hold_queues[] = { 1103 MAIL_QUEUE_INCOMING, 1104 MAIL_QUEUE_ACTIVE, 1105 MAIL_QUEUE_DEFERRED, 1106 0, 1107 }; 1108 static char *default_release_queues[] = { 1109 MAIL_QUEUE_HOLD, 1110 0, 1111 }; 1112 1113 /* 1114 * Fingerprint executables and core dumps. 1115 */ 1116 MAIL_VERSION_STAMP_ALLOCATE; 1117 1118 /* 1119 * Be consistent with file permissions. 1120 */ 1121 umask(022); 1122 1123 /* 1124 * To minimize confusion, make sure that the standard file descriptors 1125 * are open before opening anything else. XXX Work around for 44BSD where 1126 * fstat can return EBADF on an open file descriptor. 1127 */ 1128 for (fd = 0; fd < 3; fd++) 1129 if (fstat(fd, &st) == -1 1130 && (close(fd), open("/dev/null", O_RDWR, 0)) != fd) 1131 msg_fatal("open /dev/null: %m"); 1132 1133 /* 1134 * Process this environment option as early as we can, to aid debugging. 1135 */ 1136 if (safe_getenv(CONF_ENV_VERB)) 1137 msg_verbose = 1; 1138 1139 /* 1140 * Initialize logging. 1141 */ 1142 if ((slash = strrchr(argv[0], '/')) != 0 && slash[1]) 1143 argv[0] = slash + 1; 1144 msg_vstream_init(argv[0], VSTREAM_ERR); 1145 msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); 1146 set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); 1147 1148 /* 1149 * Check the Postfix library version as soon as we enable logging. 1150 */ 1151 MAIL_VERSION_CHECK; 1152 1153 /* 1154 * Disallow unsafe practices, and refuse to run set-uid (or as the child 1155 * of a set-uid process). Whenever a privileged wrapper program is 1156 * needed, it must properly sanitize the real/effective/saved UID/GID, 1157 * the secondary groups, the process environment, and so on. Otherwise, 1158 * accidents can happen. If not with Postfix, then with other software. 1159 */ 1160 if (unsafe() != 0) 1161 msg_fatal("this postfix command must not run as a set-uid process"); 1162 if (getuid()) 1163 msg_fatal("use of this command is reserved for the superuser"); 1164 1165 /* 1166 * Parse JCL. 1167 */ 1168 while ((c = GETOPT(argc, argv, "c:d:h:H:pr:sSv")) > 0) { 1169 switch (c) { 1170 default: 1171 msg_fatal("usage: %s " 1172 "[-c config_dir] " 1173 "[-d queue_id (delete)] " 1174 "[-h queue_id (hold)] [-H queue_id (un-hold)] " 1175 "[-p (purge temporary files)] [-r queue_id (requeue)] " 1176 "[-s (structure fix)] [-S (redundant structure fix)]" 1177 "[-v (verbose)] [queue...]", argv[0]); 1178 case 'c': 1179 if (*optarg != '/') 1180 msg_fatal("-c requires absolute pathname"); 1181 if (setenv(CONF_ENV_PATH, optarg, 1) < 0) 1182 msg_fatal("setenv: %m"); 1183 break; 1184 case 'd': 1185 if (delete_names == 0) 1186 delete_names = argv_alloc(1); 1187 argv_add(delete_names, optarg, (char *) 0); 1188 action |= (strcmp(optarg, "ALL") == 0 ? 1189 ACTION_DELETE_ALL : ACTION_DELETE_ONE); 1190 break; 1191 case 'h': 1192 if (hold_names == 0) 1193 hold_names = argv_alloc(1); 1194 argv_add(hold_names, optarg, (char *) 0); 1195 action |= (strcmp(optarg, "ALL") == 0 ? 1196 ACTION_HOLD_ALL : ACTION_HOLD_ONE); 1197 break; 1198 case 'H': 1199 if (release_names == 0) 1200 release_names = argv_alloc(1); 1201 argv_add(release_names, optarg, (char *) 0); 1202 action |= (strcmp(optarg, "ALL") == 0 ? 1203 ACTION_RELEASE_ALL : ACTION_RELEASE_ONE); 1204 break; 1205 case 'p': 1206 action |= ACTION_PURGE; 1207 break; 1208 case 'r': 1209 if (requeue_names == 0) 1210 requeue_names = argv_alloc(1); 1211 argv_add(requeue_names, optarg, (char *) 0); 1212 action |= (strcmp(optarg, "ALL") == 0 ? 1213 ACTION_REQUEUE_ALL : ACTION_REQUEUE_ONE); 1214 break; 1215 case 'S': 1216 action |= ACTION_STRUCT_RED; 1217 /* FALLTHROUGH */ 1218 case 's': 1219 action |= ACTION_STRUCT; 1220 break; 1221 case 'v': 1222 msg_verbose++; 1223 break; 1224 } 1225 } 1226 1227 /* 1228 * Read the global configuration file and extract configuration 1229 * information. The -c command option can override the default 1230 * configuration directory location. 1231 */ 1232 mail_conf_read(); 1233 /* Re-evaluate mail_task() after reading main.cf. */ 1234 msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); 1235 if (chdir(var_queue_dir)) 1236 msg_fatal("chdir %s: %m", var_queue_dir); 1237 1238 /* 1239 * All file/directory updates must be done as the mail system owner. This 1240 * is because Postfix daemons manipulate the queue with those same 1241 * privileges, so directories must be created with the right ownership. 1242 * 1243 * Running as a non-root user is also required for security reasons. When 1244 * the Postfix queue hierarchy is compromised, an attacker could trick us 1245 * into entering other file hierarchies and afflicting damage. Running as 1246 * a non-root user limits the damage to the already compromised mail 1247 * owner. 1248 */ 1249 set_ugid(var_owner_uid, var_owner_gid); 1250 1251 /* 1252 * Be sure to log a warning if we do not finish structural repair. Maybe 1253 * we should have an fsck-style "clean" flag so Postfix will not start 1254 * with a broken queue. 1255 * 1256 * Set up signal handlers after permanently dropping super-user privileges, 1257 * so that signal handlers will always run with the correct privileges. 1258 * 1259 * XXX Don't enable SIGHUP or SIGTERM if it was ignored by the parent. 1260 * 1261 * interrupted() uses the in-kernel SIGINT handler address as an atomic 1262 * variable to prevent nested interrupted() calls. For this reason, the 1263 * SIGINT handler must be configured before other signal handlers are 1264 * allowed to invoke interrupted(). See also similar code in postdrop. 1265 */ 1266 signal(SIGINT, interrupted); 1267 signal(SIGQUIT, interrupted); 1268 if (signal(SIGTERM, SIG_IGN) == SIG_DFL) 1269 signal(SIGTERM, interrupted); 1270 if (signal(SIGHUP, SIG_IGN) == SIG_DFL) 1271 signal(SIGHUP, interrupted); 1272 msg_cleanup(fatal_warning); 1273 1274 /* 1275 * Sanity checks. 1276 */ 1277 if ((action & ACTION_DELETE_ALL) && (action & ACTION_DELETE_ONE)) { 1278 msg_warn("option \"-d ALL\" will ignore other command line queue IDs"); 1279 action &= ~ACTION_DELETE_ONE; 1280 } 1281 if ((action & ACTION_REQUEUE_ALL) && (action & ACTION_REQUEUE_ONE)) { 1282 msg_warn("option \"-r ALL\" will ignore other command line queue IDs"); 1283 action &= ~ACTION_REQUEUE_ONE; 1284 } 1285 if ((action & ACTION_HOLD_ALL) && (action & ACTION_HOLD_ONE)) { 1286 msg_warn("option \"-h ALL\" will ignore other command line queue IDs"); 1287 action &= ~ACTION_HOLD_ONE; 1288 } 1289 if ((action & ACTION_RELEASE_ALL) && (action & ACTION_RELEASE_ONE)) { 1290 msg_warn("option \"-H ALL\" will ignore other command line queue IDs"); 1291 action &= ~ACTION_RELEASE_ONE; 1292 } 1293 1294 /* 1295 * Execute the explicitly specified (or default) action, on the 1296 * explicitly specified (or default) queues. 1297 * 1298 * XXX Work around gcc const brain damage. 1299 * 1300 * XXX The file name/inode number fix should always run over all message 1301 * file directories, and should always be preceded by a subdirectory 1302 * level check of the bounce and defer logfile directories. 1303 */ 1304 if (action == 0) 1305 action = ACTION_DEFAULT; 1306 if (argv[optind] != 0) 1307 queues = (const char **) argv + optind; 1308 else if (action == ACTION_HOLD_ALL) 1309 queues = (const char **) default_hold_queues; 1310 else if (action == ACTION_RELEASE_ALL) 1311 queues = (const char **) default_release_queues; 1312 else 1313 queues = (const char **) default_queues; 1314 1315 /* 1316 * Basic queue maintenance, as well as mass deletion, mass requeuing, and 1317 * mass name-to-inode fixing. This ensures that queue files are in the 1318 * right place before the file-by-name operations are done. 1319 */ 1320 if (action & ~ACTIONS_BY_QUEUE_ID) 1321 super(queues, action); 1322 1323 /* 1324 * If any file names needed changing to match the message file inode 1325 * number, those files were named newqeueid#FIX. We need a second pass to 1326 * strip the suffix from the new queue ID, and to complete any requested 1327 * operations that had to be skipped in the first pass. 1328 */ 1329 if (inode_mismatch > 0) 1330 super(queues, action); 1331 1332 /* 1333 * Don't do actions by queue file name if any queue files changed name 1334 * because they did not match the queue file inode number. We could be 1335 * acting on the wrong queue file and lose mail. 1336 */ 1337 if ((action & ACTIONS_BY_QUEUE_ID) 1338 && (inode_mismatch > 0 || inode_fixed > 0)) { 1339 msg_error("QUEUE FILE NAMES WERE CHANGED TO MATCH INODE NUMBERS"); 1340 msg_fatal("CHECK YOUR QUEUE IDS AND RE-ISSUE THE COMMAND"); 1341 } 1342 1343 /* 1344 * Delete queue files by name. This must not be done when queue file 1345 * names have changed names as a result of inode number mismatches, 1346 * because we could be deleting the wrong message. 1347 */ 1348 if (action & ACTION_DELETE_ONE) { 1349 argv_terminate(delete_names); 1350 queues = (const char **) 1351 (argv[optind] ? argv + optind : default_queues); 1352 for (cpp = delete_names->argv; *cpp; cpp++) { 1353 if (strcmp(*cpp, "ALL") == 0) 1354 continue; 1355 if (strcmp(*cpp, "-") == 0) 1356 message_deleted += 1357 operate_stream(VSTREAM_IN, delete_one, queues); 1358 else 1359 message_deleted += delete_one(queues, *cpp); 1360 } 1361 } 1362 1363 /* 1364 * Requeue queue files by name. This must not be done when queue file 1365 * names have changed names as a result of inode number mismatches, 1366 * because we could be requeuing the wrong message. 1367 */ 1368 if (action & ACTION_REQUEUE_ONE) { 1369 argv_terminate(requeue_names); 1370 queues = (const char **) 1371 (argv[optind] ? argv + optind : default_queues); 1372 for (cpp = requeue_names->argv; *cpp; cpp++) { 1373 if (strcmp(*cpp, "ALL") == 0) 1374 continue; 1375 if (strcmp(*cpp, "-") == 0) 1376 message_requeued += 1377 operate_stream(VSTREAM_IN, requeue_one, queues); 1378 else 1379 message_requeued += requeue_one(queues, *cpp); 1380 } 1381 } 1382 1383 /* 1384 * Put on hold queue files by name. This must not be done when queue file 1385 * names have changed names as a result of inode number mismatches, 1386 * because we could put on hold the wrong message. 1387 */ 1388 if (action & ACTION_HOLD_ONE) { 1389 argv_terminate(hold_names); 1390 queues = (const char **) 1391 (argv[optind] ? argv + optind : default_hold_queues); 1392 for (cpp = hold_names->argv; *cpp; cpp++) { 1393 if (strcmp(*cpp, "ALL") == 0) 1394 continue; 1395 if (strcmp(*cpp, "-") == 0) 1396 message_held += 1397 operate_stream(VSTREAM_IN, hold_one, queues); 1398 else 1399 message_held += hold_one(queues, *cpp); 1400 } 1401 } 1402 1403 /* 1404 * Take "off hold" queue files by name. This must not be done when queue 1405 * file names have changed names as a result of inode number mismatches, 1406 * because we could take off hold the wrong message. 1407 */ 1408 if (action & ACTION_RELEASE_ONE) { 1409 argv_terminate(release_names); 1410 queues = (const char **) 1411 (argv[optind] ? argv + optind : default_release_queues); 1412 for (cpp = release_names->argv; *cpp; cpp++) { 1413 if (strcmp(*cpp, "ALL") == 0) 1414 continue; 1415 if (strcmp(*cpp, "-") == 0) 1416 message_released += 1417 operate_stream(VSTREAM_IN, release_one, queues); 1418 else 1419 message_released += release_one(queues, *cpp); 1420 } 1421 } 1422 1423 /* 1424 * Report. 1425 */ 1426 if (message_requeued > 0) 1427 msg_info("Requeued: %d message%s", message_requeued, 1428 message_requeued > 1 ? "s" : ""); 1429 if (message_deleted > 0) 1430 msg_info("Deleted: %d message%s", message_deleted, 1431 message_deleted > 1 ? "s" : ""); 1432 if (message_held > 0) 1433 msg_info("Placed on hold: %d message%s", 1434 message_held, message_held > 1 ? "s" : ""); 1435 if (message_released > 0) 1436 msg_info("Released from hold: %d message%s", 1437 message_released, message_released > 1 ? "s" : ""); 1438 if (inode_fixed > 0) 1439 msg_info("Renamed to match inode number: %d message%s", inode_fixed, 1440 inode_fixed > 1 ? "s" : ""); 1441 if (inode_mismatch > 0 || inode_fixed > 0) 1442 msg_warn("QUEUE FILE NAMES WERE CHANGED TO MATCH INODE NUMBERS"); 1443 1444 /* 1445 * Clean up. 1446 */ 1447 if (requeue_names) 1448 argv_free(requeue_names); 1449 if (delete_names) 1450 argv_free(delete_names); 1451 if (hold_names) 1452 argv_free(hold_names); 1453 if (release_names) 1454 argv_free(release_names); 1455 1456 exit(0); 1457 } 1458