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