Distant derivative of code by Michael Tokarev. File:
smtpd/smtpd.c.
+20011228
+
+ Bugfix: a readlline() error message showed less text than
+ intended. Christian von Roques.
+
+ Cleanup: postfix now installs with group-writable maildrop
+ directory and with a set-gid postdrop mail submission
+ command. The pickup service is now unprivileged. The
+ world-writable maildrop directory no longer exists.
+
+ The cleanup service is now public, in preparation for local
+ sendmail/postdrop mail submission that avoids the maildrop
+ queue directory while Postfix is up.
+
+ Cleanup: moved the main.cf/master.cf file editing from the
+ postfix-script file to the INSTALL.sh file.
+
+ Cleanup: INSTALL.sh no longer accepts "no" as the destination
+ of Postfix manual pages.
+
+20011230
+
+ Cleanup: the code for "mailq", "sendmail -q", and for
+ "sendmail -qRsite" was moved from the sendmail command to
+ a new set-gid postqueue command. The pickup and qmgr FIFOs
+ are no longer world writable.
+
Open problems:
+ Low: don't do user@domain and @domain lookups in
+ local_recipient_maps queries.
+
Low: after reorganizing configuration parameters, add flags
to all parameters whose value can be read from file.
In order to install or upgrade Postfix:
-- Create a user "postfix" with a unique user id and group id.
- Preferably, this is an account that no-one can log into. The
- account does not need an executable login shell, and needs no
- existing home directory. My password file entry looks like this:
+- Create a user account "postfix" with a user id and group id that
+ are not used by any other user account. Preferably, this is an
+ account that no-one can log into. The account does not need an
+ executable login shell, and needs no existing home directory.
+ My password file entry looks like this:
postfix:*:12345:12345:postfix:/no/where:/no/shell
postfix: root
-- Review section 12 of this file, and decide if a world-writable
- maildrop is OK, or if Postfix needs a set-gid posting agent.
+- Create a group "postdrop" with a group id that is not used by
+ any other user account. Not even by the postfix user account.
+ My group file entry looks like:
+
+ postdrop:*:54321:
+
+ NB: this group was optional with older Postfix releases; it is
+ now required.
- Run the INSTALL.sh script as the super-user:
user agent so that it calls the Postfix sendmail program directly.
Follow the instructions in the "Mandatory configuration file edits"
-in section 10, review the "To chroot or not to chroot" text in
-section 11, and choose a security model according to section 12.
+in section 10, and review the "To chroot or not to chroot" text in
+section 11.
You MUST comment out the `smtp inet' entry in /etc/postfix/master.cf,
in order to avoid conflicts with the real sendmail.
mydestination = $myhostname
Follow the instructions in the "Mandatory configuration file edits"
-in section 10, review the "To chroot or not to chroot" text in
-section 11, and choose a security model according to section 12.
+in section 10, and review the "To chroot or not to chroot" text in
+section 11.
Start the mail system:
collection of scripts that help you set up chroot environments for
Postfix systems.
-12 - Security: writable versus protected maildrop directory
-===========================================================
-
-Postfix offers a choice of submission mechanisms.
-
-1 - Postfix can use a world-writable, sticky, mode 1733 maildrop
- directory where local users can submit mail. This approach
- avoids the need for set-uid or set-gid software. Mail can be
- posted even while the mail system is down. Queue files in the
- maildrop directory have no read/write/execute permission for
- other users. The maildrop directory is not used for mail
- received via the network.
-
- With directory world write permission come opportunities for
- annoyance: a local user can make hard links to someone else's
- maildrop files so they don't go away and may be delivered
- multiple times; a local user can fill the maildrop directory
- with junk and try to crash the mail system; and a local user
- can hard link someone else's files into the maildrop directory
- and try to have them delivered as mail. However, Postfix queue
- files have a specific format; less than one in 10^12 non-Postfix
- files would be recognized as a valid Postfix queue file.
-
- In order to enable maildrop world-write permission:
-
- - Specify "no" when asked by the INSTALL.sh script whether
- Postfix needs set-gid privileges.
-
-2 - On systems with many users it may be desirable to revoke maildrop
- directory world write permission, and to enable set-gid privileges
- on a small "maildrop" command that is provided for this purpose.
-
- In order to revoke maildrop world-write permission:
-
- - Create a group "maildrop" that is unique and that does not
- share its group ID with any other user, certainly not with
- the postfix account,
-
- - Specify "maildrop" when asked by the INSTALL.sh script whether
- Postfix needs set-gid privileges.
-
- The sendmail posting program will automatically invoke the
- postdrop command when maildrop directory write permission is
- restricted.
-
-13 - Care and feeding of the Postfix system
+12 - Care and feeding of the Postfix system
===========================================
The Postfix programs log all problems to the syslog daemon. The
newaliases_path - full pathname of the Postfix newaliases command.
mailq_path - full pathname of the Postfix mailq command.
- mail_owner - owner of Postfix queue files.
+ mail_owner - Postfix queue account (with unique user/group id numbers).
+
+ setgid - group for submission (with a unique group id number).
- setgid - groupname, e.g., postdrop (default: no). See INSTALL section 12.
manpages - "no" or path to man tree. Example: /usr/local/man.
EOF
: ${newaliases_path=/usr/bin/newaliases}
: ${mailq_path=/usr/bin/mailq}
: ${mail_owner=postfix}
-: ${setgid=no}
+: ${setgid=postdrop}
: ${manpages=/usr/local/man}
# Find out the location of configuration files.
do
case $path in
/*) ;;
- no) ;;
*) echo Error: $path should be an absolute path name. 1>&2; exit 1;;
esac
done
exit 1
}
-case $setgid in
-no) ;;
- *) chgrp "$setgid" $tempdir/junk >/dev/null 2>&1 || {
- echo Error: $setgid needs an entry in the group file. 1>&2
- echo Remember, $setgid must have a dedicated group id. 1>&2
- exit 1
- }
-esac
+chgrp "$setgid" $tempdir/junk >/dev/null 2>&1 || {
+ echo Error: $setgid needs an entry in the group file. 1>&2
+ echo Remember, $setgid must have a dedicated group id. 1>&2
+ exit 1
+}
rm -f $tempdir/junk
compare_or_move a+x,go-w $tempdir/junk $CONFIG_DIRECTORY/install.cf || exit 1
rm -f $tempdir/junk
-# Use set-gid privileges instead of writable maildrop (optional).
+compare_or_replace a+x,go-w conf/postfix-script $CONFIG_DIRECTORY/postfix-script ||
+ exit 1
-test -d $QUEUE_DIRECTORY/maildrop || {
- mkdir -p $QUEUE_DIRECTORY/maildrop || exit 1
- chown $mail_owner $QUEUE_DIRECTORY/maildrop || exit 1
-}
+# Install manual pages.
-case $setgid in
-no)
- chmod 1733 $QUEUE_DIRECTORY/maildrop || exit 1
- chmod g-s $COMMAND_DIRECTORY/postdrop || exit 1
- postfix_script=conf/postfix-script-nosgid
- ;;
- *)
- chgrp $setgid $COMMAND_DIRECTORY/postdrop || exit 1
- chmod g+s $COMMAND_DIRECTORY/postdrop || exit 1
- chgrp $setgid $QUEUE_DIRECTORY/maildrop || exit 1
- chmod 1730 $QUEUE_DIRECTORY/maildrop || exit 1
- postfix_script=conf/postfix-script-sgid
- ;;
-esac
+(cd man || exit 1
+for dir in man?
+ do test -d $MANPAGES/$dir || mkdir -p $MANPAGES/$dir || exit 1
+done
+for file in `censored_ls man?/*`
+do
+ (test -f $MANPAGES/$file && cmp -s $file $MANPAGES/$file &&
+ echo Skipping $MANPAGES/$file...) || {
+ echo Updating $MANPAGES/$file...
+ rm -f $MANPAGES/$file
+ cp $file $MANPAGES/$file || exit 1
+ chmod 644 $MANPAGES/$file || exit 1
+ }
+done)
-compare_or_replace a+x,go-w $postfix_script $CONFIG_DIRECTORY/postfix-script ||
- exit 1
+# Use set-gid/group privileges for restricted access.
-# Install manual pages (optional).
-
-case $manpages in
-no) ;;
- *) (
- cd man || exit 1
- for dir in man?
- do test -d $MANPAGES/$dir || mkdir -p $MANPAGES/$dir || exit 1
- done
- for file in `censored_ls man?/*`
- do
- (test -f $MANPAGES/$file && cmp -s $file $MANPAGES/$file &&
- echo Skipping $MANPAGES/$file...) || {
- echo Updating $MANPAGES/$file...
- rm -f $MANPAGES/$file
- cp $file $MANPAGES/$file || exit 1
- chmod 644 $MANPAGES/$file || exit 1
- }
- done
- )
-esac
+for directory in maildrop
+do
+ test -d $QUEUE_DIRECTORY/$directory || {
+ mkdir -p $QUEUE_DIRECTORY/$directory || exit 1
+ chown $mail_owner $QUEUE_DIRECTORY/$directory || exit 1
+ }
+ # Fix group if upgrading from world-writable maildrop.
+ chgrp $setgid $QUEUE_DIRECTORY/$directory || exit 1
+ chmod 730 $QUEUE_DIRECTORY/$directory || exit 1
+done
+
+for directory in public
+do
+ test -d $QUEUE_DIRECTORY/$directory || {
+ mkdir -p $QUEUE_DIRECTORY/$directory || exit 1
+ chown $mail_owner $QUEUE_DIRECTORY/$directory || exit 1
+ }
+ # Fix group if upgrading from world-accessible directory.
+ chgrp $setgid $QUEUE_DIRECTORY/$directory || exit 1
+ chmod 710 $QUEUE_DIRECTORY/$directory || exit 1
+done
+
+for directory in pid
+do
+ test -d $QUEUE_DIRECTORY/$directory && {
+ chown root $QUEUE_DIRECTORY/$directory || exit 1
+ }
+done
+
+chgrp $setgid $COMMAND_DIRECTORY/postdrop $COMMAND_DIRECTORY/postqueue || exit 1
+chmod g+s $COMMAND_DIRECTORY/postdrop $COMMAND_DIRECTORY/postqueue || exit 1
+
+grep 'flush.*flush' $CONFIG_DIRECTORY/master.cf >/dev/null || {
+ echo adding missing entry for flush service to master.cf
+ cat >>$CONFIG_DIRECTORY/master.cf <<EOF
+flush unix - - n 1000? 0 flush
+EOF
+}
+
+grep "^pickup[ ]*fifo[ ]*n[ ]*n" \
+ $CONFIG_DIRECTORY/master.cf >/dev/null && {
+ echo changing master.cf, making the pickup service unprivileged
+ ed $CONFIG_DIRECTORY/master.cf <<EOF
+/^pickup[ ]*fifo[ ]*n[ ]*n/
+s/\(n[ ]*\)n/\1-/
+w
+q
+EOF
+}
+grep "^cleanup[ ]*unix[ ]*-" \
+ $CONFIG_DIRECTORY/master.cf >/dev/null && {
+ echo changing master.cf, making the cleanup service public
+ ed $CONFIG_DIRECTORY/master.cf <<EOF
+/^cleanup[ ]*unix[ ]*-/
+s/-/n/
+w
+q
+EOF
+}
+
+found=`bin/postconf -c $CONFIG_DIRECTORY -h hash_queue_names`
+missing=
+(echo "$found" | grep active >/dev/null) || missing="$missing active"
+(echo "$found" | grep bounce >/dev/null) || missing="$missing bounce"
+(echo "$found" | grep defer >/dev/null) || missing="$missing defer"
+(echo "$found" | grep flush >/dev/null) || missing="$missing flush"
+(echo "$found" | grep incoming>/dev/null)|| missing="$missing incoming"
+(echo "$found" | grep deferred>/dev/null)|| missing="$missing deferred"
+test -n "$missing" && {
+ echo fixing main.cf hash_queue_names for missing $missing
+ bin/postconf -c $CONFIG_DIRECTORY -e hash_queue_names="$found$missing"
+}
test "$need_config" = 1 || exit 0
src/sendmail src/error src/pickup src/cleanup src/smtpd src/local \
src/lmtp src/trivial-rewrite src/qmgr src/smtp src/bounce src/pipe \
src/showq src/postalias src/postcat src/postconf src/postdrop \
- src/postkick src/postlock src/postlog src/postmap src/postsuper \
- src/nqmgr src/qmqpd src/spawn src/flush src/virtual # proto man html
+ src/postkick src/postlock src/postlog src/postmap src/postqueue \
+ src/postsuper src/nqmgr src/qmqpd src/spawn src/flush src/virtual \
+ # proto man html
default: update
@domain) that is normally done with Postfix access control tables,
canonical maps and virtual maps.
-As a side effect, pcre maps can only match user@domain strings, so
-that regexps cannot be used for local alias database lookups. That
-would be a security exposure anyway.
+An additional restriction is that regular expression tables cannot
+cannot be used for local alias database lookups. That would be a
+security exposure anyway.
+Incompatible changes with snapshot-20011230
+===========================================
+
+This release modifies the existing master.cf file, making the local
+pickup unprivileged, and making the cleanup service "public" (for
+future performance improvements of local mail submission).
+
+Should you have to back out to a previous release, then you have
+to edit the master.cf file, making the pickup service "privileged",
+and making the cleanup service "private".
+
+Major changes with snapshot-20011230
+====================================
+
+Simplification of the local Postfix security model.
+
+- The world-writable maildrop directory is gone. Postfix now uses
+ the set-gid postdrop command for local mail submissions. The
+ local mail pickup daemon is now an unprivileged process.
+
+- The world-writable pickup and queue manager FIFOs are gone.
+ Postfix now uses the new set-gid postqueue command for all the
+ queue operations that were implemented by the Postfix sendmail
+ command.
+
Incompatible changes with snapshot-20011226
===========================================
# ==========================================================================
smtp inet n - n - - smtpd
#628 inet n - n - - qmqpd
-pickup fifo n n n 60 1 pickup
-cleanup unix - - n - 0 cleanup
+pickup fifo n - n 60 1 pickup
+cleanup unix n - n - 0 cleanup
qmgr fifo n - n 300 1 qmgr
#qmgr fifo n - n 300 1 nqmgr
rewrite unix - - n - - trivial-rewrite
#!/bin/sh
-echo Please read the SECURITY notes at the end of the INSTALL document 1>&2
+#++
+# NAME
+# postfix-script 1
+# SUMMARY
+# execute Postfix administrative commands
+# SYNOPSIS
+# \fBpostfix-script\fR \fIcommand\fR
+# DESCRIPTION
+# The \fBfBpostfix-script\fR script executes Postfix administrative
+# commands in an environtment that is set up by the \fBpostfix\fR(1)
+# command.
+# SEE ALSO
+# master(8) Postfix master program
+# postfix(1) Postfix administrative interface
+# LICENSE
+# .ad
+# .fi
+# The Secure Mailer license must be distributed with this software.
+# AUTHOR(S)
+# Wietse Venema
+# IBM T.J. Watson Research
+# P.O. Box 704
+# Yorktown Heights, NY 10598, USA
+#--
+
+# Avoid POSIX death due to SIGHUP when some parent process exits.
+
+trap '' 1
+
+case $daemon_directory in
+"") echo This script must be run by the postfix command. 1>&2
+ echo Do not run directly. 1>&2
+ exit 1
+esac
+
+LOGGER="$command_directory/postlog -t $MAIL_LOGTAG/postfix-script"
+INFO="$LOGGER -p info"
+WARN="$LOGGER -p warn"
+ERROR="$LOGGER -p error"
+FATAL="$LOGGER -p fatal"
+PANIC="$LOGGER -p panic"
+
+umask 022
+
+#
+# LINUX by default does not synchronously update directories -
+# that's dangerous for mail.
+#
+if [ -f /usr/bin/chattr ]
+then
+ CHATTR="/usr/bin/chattr +S"
+else
+ CHATTR=:
+fi
+
+#
+# Can't do much without these in place.
+#
+cd $command_directory || {
+ $FATAL no Postfix command directory $command_directory!
+ exit 1
+}
+cd $daemon_directory || {
+ $FATAL no Postfix daemon directory $daemon_directory!
+ exit 1
+}
+test -f master || {
+ $FATAL no Postfix master program $daemon_directory/master!
+ exit 1
+}
+cd $config_directory || {
+ $FATAL no Postfix configuration directory $config_directory!
+ exit 1
+}
+cd $queue_directory || {
+ $FATAL no Postfix queue directory $queue_directory!
+ exit 1
+}
+
+#
+# Parse JCL
+#
+case $1 in
+
+start_msg)
+
+ echo "Start postfix"
+ ;;
+
+stop_msg)
+
+ echo "Stop postfix"
+ ;;
+
+start)
+
+ $daemon_directory/master -t 2>/dev/null || {
+ $FATAL the Postfix mail system is already running
+ exit 1
+ }
+ $config_directory/postfix-script check || {
+ $FATAL Postfix integrity check failed!
+ exit 1
+ }
+ $INFO starting the Postfix mail system
+ $daemon_directory/master &
+ ;;
+
+drain)
+
+ $daemon_directory/master -t 2>/dev/null && {
+ $FATAL the Postfix mail system is not running
+ exit 1
+ }
+ $INFO stopping the Postfix mail system
+ kill -9 `sed 1q pid/master.pid`
+ ;;
+
+stop)
+
+ $daemon_directory/master -t 2>/dev/null && {
+ $FATAL the Postfix mail system is not running
+ exit 1
+ }
+ $INFO stopping the Postfix mail system
+ kill `sed 1q pid/master.pid`
+ ;;
+
+abort)
+
+ $daemon_directory/master -t 2>/dev/null && {
+ $FATAL the Postfix mail system is not running
+ exit 1
+ }
+ $INFO aborting the Postfix mail system
+ kill `sed 1q pid/master.pid`
+ ;;
+
+reload)
+
+ $daemon_directory/master -t 2>/dev/null && {
+ $FATAL the Postfix mail system is not running
+ exit 1
+ }
+ $INFO refreshing the Postfix mail system
+ $command_directory/postsuper active || exit 1
+ kill -HUP `sed 1q pid/master.pid`
+ $command_directory/postsuper &
+ ;;
+
+flush)
+
+ cd $queue_directory || {
+ $FATAL no Postfix queue directory $queue_directory!
+ exit 1
+ }
+ $command_directory/postqueue -f
+ ;;
+
+check)
+
+ for dir in $daemon_directory $config_directory $queue_directory
+ do
+ ls -lLd $dir | (grep " root " >/dev/null ||
+ $WARN not owned by root: $dir)
+ done
+
+ find $daemon_directory/* $config_directory/* ! -user root \
+ -exec $WARN not owned by root: {} \;
+
+ find $daemon_directory/. $config_directory/. \
+ \( -perm -020 -o -perm -002 \) -type f \
+ -exec $WARN group or other writable: {} \;
+
+ test -d maildrop || {
+ $WARN creating missing Postfix maildrop directory
+ mkdir maildrop || exit 1
+ chmod 730 maildrop || exit 1
+ chown $mail_owner maildrop || exit 1
+ (. $config_directory/install.cf; chgrp $setgid maildrop)
+ }
+ test -d pid || {
+ $WARN creating missing Postfix pid directory
+ mkdir pid || exit 1
+ chmod 755 pid || exit 1
+ }
+ for dir in incoming active bounce defer deferred flush saved corrupt; do
+ test -d $dir || {
+ $WARN creating missing Postfix $dir directory
+ mkdir $dir || exit 1
+ chmod 700 $dir || exit 1
+ $CHATTR $dir 2>/dev/null
+ chown $mail_owner $dir || exit 1
+ }
+ done
+ test -d public || {
+ $WARN creating missing Postfix public directory
+ mkdir public || exit 1
+ chmod 710 public || exit 1
+ chown $mail_owner public || exit 1
+ }
+ test -d private || {
+ $WARN creating missing Postfix private directory
+ mkdir private || exit 1
+ chmod 700 private || exit 1
+ chown $mail_owner private || exit 1
+ }
+ find `ls -d $queue_directory/* | \
+ egrep '/(incoming|active|defer|deferred|bounce|saved|corrupt|public|private|flush)$'` \
+ ! \( -type p -o -type s \) ! -user $mail_owner \
+ -exec $WARN not owned by $mail_owner: {} \;
+
+ for name in `ls -d $queue_directory/* | \
+ egrep '/(bin|etc|lib|usr)$'` ; \
+ do \
+ find $name ! -user root \
+ -exec $WARN not owned by root: {} \; ; \
+ done
+
+ for dir in $queue_directory/maildrop
+ do
+ ls -lLd $dir | (grep " $mail_owner " >/dev/null ||
+ $WARN not owned by $mail_owner: $dir)
+ done
+
+ for dir in bin etc lib sbin usr
+ do
+ test -d $dir && find $dir -type f -print | while read path
+ do
+ cmp -s $path /$path ||
+ $WARN $queue_directory/$path and /$path differ
+ done
+ done
+
+ # Look for incomplete upgrades.
+
+ test -f $config_directory/master.cf || {
+ $FATAL no $config_directory/master.cf file found
+ exit 1
+ }
+
+ # See if all queue files are in the right place. This is slow.
+ # We must scan all queues for mis-named queue files before the
+ # mail system can run.
+
+ $command_directory/postsuper || exit 1
+
+ find corrupt -type f -exec $WARN damaged message: {} \;
+
+ # XXX also: look for weird stuff, weird permissions, etc.
+ ;;
+
+*)
+
+ $FATAL "usage: postfix start (or stop, reload, abort, flush, or check)"
+ exit 1
+ ;;
+
+esac
+++ /dev/null
-*** postfix-script-nosgid Thu May 24 17:13:59 2001
---- postfix-script-sgid Fri Jun 29 10:28:19 2001
-***************
-*** 177,184 ****
- test -d maildrop || {
- $WARN creating missing Postfix maildrop directory
- mkdir maildrop || exit 1
-! chmod 1733 maildrop
- chown $mail_owner maildrop
- }
- test -d pid || {
- $WARN creating missing Postfix pid directory
---- 177,185 ----
- test -d maildrop || {
- $WARN creating missing Postfix maildrop directory
- mkdir maildrop || exit 1
-! chmod 1730 maildrop
- chown $mail_owner maildrop
-+ (. $config_directory/install.cf; chgrp $setgid maildrop)
- }
- test -d pid || {
- $WARN creating missing Postfix pid directory
+++ /dev/null
-#!/bin/sh
-
-#++
-# NAME
-# postfix-script 1
-# SUMMARY
-# execute Postfix administrative commands
-# SYNOPSIS
-# \fBpostfix-script\fR \fIcommand\fR
-# DESCRIPTION
-# The \fBfBpostfix-script\fR script executes Postfix administrative
-# commands in an environtment that is set up by the \fBpostfix\fR(1)
-# command.
-# SEE ALSO
-# master(8) Postfix master program
-# postfix(1) Postfix administrative interface
-# LICENSE
-# .ad
-# .fi
-# The Secure Mailer license must be distributed with this software.
-# AUTHOR(S)
-# Wietse Venema
-# IBM T.J. Watson Research
-# P.O. Box 704
-# Yorktown Heights, NY 10598, USA
-#--
-
-# Avoid POSIX death due to SIGHUP when some parent process exits.
-
-trap '' 1
-
-case $daemon_directory in
-"") echo This script must be run by the postfix command. 1>&2
- echo Do not run directly. 1>&2
- exit 1
-esac
-
-LOGGER="$command_directory/postlog -t $MAIL_LOGTAG/postfix-script"
-INFO="$LOGGER -p info"
-WARN="$LOGGER -p warn"
-ERROR="$LOGGER -p error"
-FATAL="$LOGGER -p fatal"
-PANIC="$LOGGER -p panic"
-
-umask 022
-
-#
-# LINUX by default does not synchronously update directories -
-# that's dangerous for mail.
-#
-if [ -f /usr/bin/chattr ]
-then
- CHATTR="/usr/bin/chattr +S"
-else
- CHATTR=:
-fi
-
-#
-# Can't do much without these in place.
-#
-cd $command_directory || {
- $FATAL no Postfix command directory $command_directory!
- exit 1
-}
-cd $daemon_directory || {
- $FATAL no Postfix daemon directory $daemon_directory!
- exit 1
-}
-test -f master || {
- $FATAL no Postfix master program $daemon_directory/master!
- exit 1
-}
-cd $config_directory || {
- $FATAL no Postfix configuration directory $config_directory!
- exit 1
-}
-cd $queue_directory || {
- $FATAL no Postfix queue directory $queue_directory!
- exit 1
-}
-
-#
-# Parse JCL
-#
-case $1 in
-
-start_msg)
-
- echo "Start postfix"
- ;;
-
-stop_msg)
-
- echo "Stop postfix"
- ;;
-
-start)
-
- $daemon_directory/master -t 2>/dev/null || {
- $FATAL the Postfix mail system is already running
- exit 1
- }
- $config_directory/postfix-script check || {
- $FATAL Postfix integrity check failed!
- exit 1
- }
- $INFO starting the Postfix mail system
- $daemon_directory/master &
- ;;
-
-drain)
-
- $daemon_directory/master -t 2>/dev/null && {
- $FATAL the Postfix mail system is not running
- exit 1
- }
- $INFO stopping the Postfix mail system
- kill -9 `sed 1q pid/master.pid`
- ;;
-
-stop)
-
- $daemon_directory/master -t 2>/dev/null && {
- $FATAL the Postfix mail system is not running
- exit 1
- }
- $INFO stopping the Postfix mail system
- kill `sed 1q pid/master.pid`
- ;;
-
-abort)
-
- $daemon_directory/master -t 2>/dev/null && {
- $FATAL the Postfix mail system is not running
- exit 1
- }
- $INFO aborting the Postfix mail system
- kill `sed 1q pid/master.pid`
- ;;
-
-reload)
-
- $daemon_directory/master -t 2>/dev/null && {
- $FATAL the Postfix mail system is not running
- exit 1
- }
- $INFO refreshing the Postfix mail system
- $command_directory/postsuper active || exit 1
- kill -HUP `sed 1q pid/master.pid`
- $command_directory/postsuper &
- ;;
-
-flush)
-
- cd $queue_directory || {
- $FATAL no Postfix queue directory $queue_directory!
- exit 1
- }
- $command_directory/postkick public qmgr IDFA
- ;;
-
-check)
-
- for dir in $daemon_directory $config_directory $queue_directory
- do
- ls -lLd $dir | (grep " root " >/dev/null ||
- $WARN not owned by root: $dir)
- done
-
- find $daemon_directory/* $config_directory/* ! -user root \
- -exec $WARN not owned by root: {} \;
-
- find $daemon_directory/. $config_directory/. \
- \( -perm -020 -o -perm -002 \) -type f \
- -exec $WARN group or other writable: {} \;
-
- test -d maildrop || {
- $WARN creating missing Postfix maildrop directory
- mkdir maildrop || exit 1
- chmod 1733 maildrop || exit 1
- chown $mail_owner maildrop || exit 1
- }
- test -d pid || {
- $WARN creating missing Postfix pid directory
- mkdir pid || exit 1
- chmod 755 pid || exit 1
- }
- for dir in incoming active bounce defer deferred flush saved corrupt; do
- test -d $dir || {
- $WARN creating missing Postfix $dir directory
- mkdir $dir || exit 1
- chmod 700 $dir || exit 1
- $CHATTR $dir 2>/dev/null
- chown $mail_owner $dir || exit 1
- }
- done
- test -d public || {
- $WARN creating missing Postfix public directory
- mkdir public || exit 1
- chmod 755 public || exit 1
- chown $mail_owner public || exit 1
- }
- test -d private || {
- $WARN creating missing Postfix private directory
- mkdir private || exit 1
- chmod 700 private || exit 1
- chown $mail_owner private || exit 1
- }
- find `ls -d $queue_directory/* | \
- egrep '/(incoming|active|defer|deferred|bounce|saved|corrupt|public|private|flush)$'` \
- ! \( -type p -o -type s \) ! -user $mail_owner \
- -exec $WARN not owned by $mail_owner: {} \;
-
- for name in `ls -d $queue_directory/* | \
- egrep '/(bin|etc|lib|usr)$'` ; \
- do \
- find $name ! -user root \
- -exec $WARN not owned by root: {} \; ; \
- done
-
- for dir in $queue_directory/maildrop
- do
- ls -lLd $dir | (grep " $mail_owner " >/dev/null ||
- $WARN not owned by $mail_owner: $dir)
- done
-
- for dir in bin etc lib sbin usr
- do
- test -d $dir && find $dir -type f -print | while read path
- do
- cmp -s $path /$path ||
- $WARN $queue_directory/$path and /$path differ
- done
- done
-
- # Look for incomplete upgrades.
-
- test -f $config_directory/master.cf || {
- $FATAL no $config_directory/master.cf file found
- exit 1
- }
- grep 'flush.*flush' $config_directory/master.cf >/dev/null || {
- $WARN adding missing entry for flush service to master.cf
- cat >>$config_directory/master.cf <<EOF
-flush unix - - n 1000? 0 flush
-EOF
- }
- found=`$command_directory/postconf -h hash_queue_names`
- missing=
- (echo "$found" | grep active >/dev/null) || missing="$missing active"
- (echo "$found" | grep bounce >/dev/null) || missing="$missing bounce"
- (echo "$found" | grep defer >/dev/null) || missing="$missing defer"
- (echo "$found" | grep flush >/dev/null) || missing="$missing flush"
- (echo "$found" | grep incoming>/dev/null)|| missing="$missing incoming"
- (echo "$found" | grep deferred>/dev/null)|| missing="$missing deferred"
- test -n "$missing" && {
- $WARN fixing main.cf hash_queue_names for missing $missing
- $command_directory/postconf -e hash_queue_names="$found$missing"
- }
-
- # See if all queue files are in the right place. This is slow.
- # We must scan all queues for mis-named queue files before the
- # mail system can run.
-
- $command_directory/postsuper || exit 1
-
- find corrupt -type f -exec $WARN damaged message: {} \;
-
- # XXX also: look for weird stuff, weird permissions, etc.
- ;;
-
-*)
-
- $FATAL "usage: postfix start (or stop, reload, abort, flush, or check)"
- exit 1
- ;;
-
-esac
+++ /dev/null
-#!/bin/sh
-
-#++
-# NAME
-# postfix-script 1
-# SUMMARY
-# execute Postfix administrative commands
-# SYNOPSIS
-# \fBpostfix-script\fR \fIcommand\fR
-# DESCRIPTION
-# The \fBfBpostfix-script\fR script executes Postfix administrative
-# commands in an environtment that is set up by the \fBpostfix\fR(1)
-# command.
-# SEE ALSO
-# master(8) Postfix master program
-# postfix(1) Postfix administrative interface
-# LICENSE
-# .ad
-# .fi
-# The Secure Mailer license must be distributed with this software.
-# AUTHOR(S)
-# Wietse Venema
-# IBM T.J. Watson Research
-# P.O. Box 704
-# Yorktown Heights, NY 10598, USA
-#--
-
-# Avoid POSIX death due to SIGHUP when some parent process exits.
-
-trap '' 1
-
-case $daemon_directory in
-"") echo This script must be run by the postfix command. 1>&2
- echo Do not run directly. 1>&2
- exit 1
-esac
-
-LOGGER="$command_directory/postlog -t $MAIL_LOGTAG/postfix-script"
-INFO="$LOGGER -p info"
-WARN="$LOGGER -p warn"
-ERROR="$LOGGER -p error"
-FATAL="$LOGGER -p fatal"
-PANIC="$LOGGER -p panic"
-
-umask 022
-
-#
-# LINUX by default does not synchronously update directories -
-# that's dangerous for mail.
-#
-if [ -f /usr/bin/chattr ]
-then
- CHATTR="/usr/bin/chattr +S"
-else
- CHATTR=:
-fi
-
-#
-# Can't do much without these in place.
-#
-cd $command_directory || {
- $FATAL no Postfix command directory $command_directory!
- exit 1
-}
-cd $daemon_directory || {
- $FATAL no Postfix daemon directory $daemon_directory!
- exit 1
-}
-test -f master || {
- $FATAL no Postfix master program $daemon_directory/master!
- exit 1
-}
-cd $config_directory || {
- $FATAL no Postfix configuration directory $config_directory!
- exit 1
-}
-cd $queue_directory || {
- $FATAL no Postfix queue directory $queue_directory!
- exit 1
-}
-
-#
-# Parse JCL
-#
-case $1 in
-
-start_msg)
-
- echo "Start postfix"
- ;;
-
-stop_msg)
-
- echo "Stop postfix"
- ;;
-
-start)
-
- $daemon_directory/master -t 2>/dev/null || {
- $FATAL the Postfix mail system is already running
- exit 1
- }
- $config_directory/postfix-script check || {
- $FATAL Postfix integrity check failed!
- exit 1
- }
- $INFO starting the Postfix mail system
- $daemon_directory/master &
- ;;
-
-drain)
-
- $daemon_directory/master -t 2>/dev/null && {
- $FATAL the Postfix mail system is not running
- exit 1
- }
- $INFO stopping the Postfix mail system
- kill -9 `sed 1q pid/master.pid`
- ;;
-
-stop)
-
- $daemon_directory/master -t 2>/dev/null && {
- $FATAL the Postfix mail system is not running
- exit 1
- }
- $INFO stopping the Postfix mail system
- kill `sed 1q pid/master.pid`
- ;;
-
-abort)
-
- $daemon_directory/master -t 2>/dev/null && {
- $FATAL the Postfix mail system is not running
- exit 1
- }
- $INFO aborting the Postfix mail system
- kill `sed 1q pid/master.pid`
- ;;
-
-reload)
-
- $daemon_directory/master -t 2>/dev/null && {
- $FATAL the Postfix mail system is not running
- exit 1
- }
- $INFO refreshing the Postfix mail system
- $command_directory/postsuper active || exit 1
- kill -HUP `sed 1q pid/master.pid`
- $command_directory/postsuper &
- ;;
-
-flush)
-
- cd $queue_directory || {
- $FATAL no Postfix queue directory $queue_directory!
- exit 1
- }
- $command_directory/postkick public qmgr IDFA
- ;;
-
-check)
-
- for dir in $daemon_directory $config_directory $queue_directory
- do
- ls -lLd $dir | (grep " root " >/dev/null ||
- $WARN not owned by root: $dir)
- done
-
- find $daemon_directory/* $config_directory/* ! -user root \
- -exec $WARN not owned by root: {} \;
-
- find $daemon_directory/. $config_directory/. \
- \( -perm -020 -o -perm -002 \) -type f \
- -exec $WARN group or other writable: {} \;
-
- test -d maildrop || {
- $WARN creating missing Postfix maildrop directory
- mkdir maildrop || exit 1
- chmod 1730 maildrop || exit 1
- chown $mail_owner maildrop || exit 1
- (. $config_directory/install.cf; chgrp $setgid maildrop)
- }
- test -d pid || {
- $WARN creating missing Postfix pid directory
- mkdir pid || exit 1
- chmod 755 pid || exit 1
- }
- for dir in incoming active bounce defer deferred flush saved corrupt; do
- test -d $dir || {
- $WARN creating missing Postfix $dir directory
- mkdir $dir || exit 1
- chmod 700 $dir || exit 1
- $CHATTR $dir 2>/dev/null
- chown $mail_owner $dir || exit 1
- }
- done
- test -d public || {
- $WARN creating missing Postfix public directory
- mkdir public || exit 1
- chmod 755 public || exit 1
- chown $mail_owner public || exit 1
- }
- test -d private || {
- $WARN creating missing Postfix private directory
- mkdir private || exit 1
- chmod 700 private || exit 1
- chown $mail_owner private || exit 1
- }
- find `ls -d $queue_directory/* | \
- egrep '/(incoming|active|defer|deferred|bounce|saved|corrupt|public|private|flush)$'` \
- ! \( -type p -o -type s \) ! -user $mail_owner \
- -exec $WARN not owned by $mail_owner: {} \;
-
- for name in `ls -d $queue_directory/* | \
- egrep '/(bin|etc|lib|usr)$'` ; \
- do \
- find $name ! -user root \
- -exec $WARN not owned by root: {} \; ; \
- done
-
- for dir in $queue_directory/maildrop
- do
- ls -lLd $dir | (grep " $mail_owner " >/dev/null ||
- $WARN not owned by $mail_owner: $dir)
- done
-
- for dir in bin etc lib sbin usr
- do
- test -d $dir && find $dir -type f -print | while read path
- do
- cmp -s $path /$path ||
- $WARN $queue_directory/$path and /$path differ
- done
- done
-
- # Look for incomplete upgrades.
-
- test -f $config_directory/master.cf || {
- $FATAL no $config_directory/master.cf file found
- exit 1
- }
- grep 'flush.*flush' $config_directory/master.cf >/dev/null || {
- $WARN adding missing entry for flush service to master.cf
- cat >>$config_directory/master.cf <<EOF
-flush unix - - n 1000? 0 flush
-EOF
- }
- found=`$command_directory/postconf -h hash_queue_names`
- missing=
- (echo "$found" | grep active >/dev/null) || missing="$missing active"
- (echo "$found" | grep bounce >/dev/null) || missing="$missing bounce"
- (echo "$found" | grep defer >/dev/null) || missing="$missing defer"
- (echo "$found" | grep flush >/dev/null) || missing="$missing flush"
- (echo "$found" | grep incoming>/dev/null)|| missing="$missing incoming"
- (echo "$found" | grep deferred>/dev/null)|| missing="$missing deferred"
- test -n "$missing" && {
- $WARN fixing main.cf hash_queue_names for missing $missing
- $command_directory/postconf -e hash_queue_names="$found$missing"
- }
-
- # See if all queue files are in the right place. This is slow.
- # We must scan all queues for mis-named queue files before the
- # mail system can run.
-
- $command_directory/postsuper || exit 1
-
- find corrupt -type f -exec $WARN damaged message: {} \;
-
- # XXX also: look for weird stuff, weird permissions, etc.
- ;;
-
-*)
-
- $FATAL "usage: postfix start (or stop, reload, abort, flush, or check)"
- exit 1
- ;;
-
-esac
COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \
postconf.1.html postfix.1.html postkick.1.html postlock.1.html \
postlog.1.html postdrop.1.html postmap.1.html sendmail.1.html \
- postsuper.1.html
+ postqueue.1.html postsuper.1.html
CONFIG = access.5.html aliases.5.html canonical.5.html relocated.5.html \
transport.5.html virtual.5.html pcre_table.5.html regexp_table.5.html
rm -f $(DAEMONS) $(COMMANDS) $(CONFIG)
bounce.8.html: ../src/bounce/bounce.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
defer.8.html: bounce.8.html
ln -s $? $@
error.8.html: ../src/error/error.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
flush.8.html: ../src/flush/flush.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
cleanup.8.html: ../src/cleanup/cleanup.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
lmtp.8.html: ../src/lmtp/lmtp.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
local.8.html: ../src/local/local.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
master.8.html: ../src/master/master.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
nqmgr.8.html: ../src/nqmgr/qmgr.c
+ PATH=../mantools:$$PATH; \
srctoman $? | sed -e 's/qmgr[^_]/n&/' \
-e 's/qmgr$$/n&/' \
-e 's/QMGR[^_]/N&/' | \
$(AWK) | nroff -man | uniq | man2html | postlink >$@
pickup.8.html: ../src/pickup/pickup.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
pipe.8.html: ../src/pipe/pipe.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
qmgr.8.html: ../src/qmgr/qmgr.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
qmqpd.8.html: ../src/qmqpd/qmqpd.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
showq.8.html: ../src/showq/showq.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
spawn.8.html: ../src/spawn/spawn.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
smtp.8.html: ../src/smtp/smtp.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
smtpd.8.html: ../src/smtpd/smtpd.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
virtual.8.html: ../src/virtual/virtual.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
trivial-rewrite.8.html: ../src/trivial-rewrite/trivial-rewrite.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
postalias.1.html: ../src/postalias/postalias.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
postcat.1.html: ../src/postcat/postcat.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
postconf.1.html: ../src/postconf/postconf.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
postdrop.1.html: ../src/postdrop/postdrop.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
postfix.1.html: ../src/postfix/postfix.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
postkick.1.html: ../src/postkick/postkick.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
postlock.1.html: ../src/postlock/postlock.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
postlog.1.html: ../src/postlog/postlog.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
postmap.1.html: ../src/postmap/postmap.c
+ PATH=../mantools:$$PATH; \
+ srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
+
+postqueue.1.html: ../src/postqueue/postqueue.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
postsuper.1.html: ../src/postsuper/postsuper.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
sendmail.1.html: ../src/sendmail/sendmail.c
+ PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
mailq.1.html: sendmail.1.html
+ PATH=../mantools:$$PATH; \
rm -f $@
ln -s $? $@
newaliases.1.html: sendmail.1.html
+ PATH=../mantools:$$PATH; \
rm -f $@
ln -s $? $@
access.5.html: ../proto/access
+ PATH=../mantools:$$PATH; \
srctoman - $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
aliases.5.html: ../proto/aliases
+ PATH=../mantools:$$PATH; \
srctoman - $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
canonical.5.html: ../proto/canonical
+ PATH=../mantools:$$PATH; \
srctoman - $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
pcre_table.5.html: ../proto/pcre_table
+ PATH=../mantools:$$PATH; \
srctoman - $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
regexp_table.5.html: ../proto/regexp_table
+ PATH=../mantools:$$PATH; \
srctoman - $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
relocated.5.html: ../proto/relocated
+ PATH=../mantools:$$PATH; \
srctoman - $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
transport.5.html: ../proto/transport
+ PATH=../mantools:$$PATH; \
srctoman - $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
virtual.5.html: ../proto/virtual
+ PATH=../mantools:$$PATH; \
srctoman - $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
<p>
<li>The <a href="postdrop.1.html">postdrop</a> command is the mail
-posting agent that is run by the <a href="sendmail.1.html">sendmail</a>
-command on systems that have no world-writable <b>maildrop</b> queue
+posting utility that is run by the <a href="sendmail.1.html">sendmail</a>
+command in order to deposit mail into the <b>maildrop</b> queue
directory.
<p>
<p>
+<li>The <a href="postqueue.1.html">postqueue</a> command is the
+utility that is run by the <a href="sendmail.1.html">sendmail</a>
+command in order to flush or list the mail queue.
+
+<p>
+
<li>The <a href="postsuper.1.html">postsuper</a> command maintains
the Postfix queue. It removes old temporary files, and moves queue
files into the right directory after a change in the hashing depth
POSTDROP(1) POSTDROP(1)
<b>NAME</b>
- postdrop - Postfix mail posting agent
+ postdrop - Postfix mail posting utility
<b>SYNOPSIS</b>
<b>postdrop</b> [<i>option</i> <i>...</i>]
The <b>postdrop</b> command creates a file in the <b>maildrop</b> direc-
tory and copies its standard input to the file.
- The command is designed to run with set-gid privileges,
- and with group write permission to the <b>maildrop</b> queue
- directory.
-
- The <b>postdrop</b> command is automatically invoked by the <a href="sendmail.1.html"><b>send-</b></a>
- <a href="sendmail.1.html"><b>mail</b>(1)</a> mail posting agent when the <b>maildrop</b> queue direc-
- tory is not world-writable.
-
Options:
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
verbose.
<b>SECURITY</b>
- This program is designed so that it can run with set-user
- (or group) id privileges.
+ The command is designed to run with set-gid privileges,
+ and with group write permission to the <b>maildrop</b> queue
+ directory.
<b>DIAGNOSTICS</b>
- Fatal errors: malformed input, I/O error, out of memory.
- Problems are logged to <b>syslogd</b>(8) and to the standard
- error stream. When the input is incomplete, or when the
- process receives a HUP, INT, QUIT or TERM signal, the
+ Fatal errors: malformed input, I/O error, out of memory.
+ Problems are logged to <b>syslogd</b>(8) and to the standard
+ error stream. When the input is incomplete, or when the
+ process receives a HUP, INT, QUIT or TERM signal, the
queue file is deleted.
<b>ENVIRONMENT</b>
- The program deletes all environment information, because
+ The program deletes most environment information, because
the C library can't be trusted.
<b>FILES</b>
/etc/postfix, configuration files
<b>CONFIGURATION</b> <b>PARAMETERS</b>
- See the Postfix <b>main.cf</b> file for syntax details and for
- default values. Use the <b>postfix</b> <b>reload</b> command after a
+ See the Postfix <b>main.cf</b> file for syntax details and for
+ default values. Use the <b>postfix</b> <b>reload</b> command after a
configuration change.
<b>import</b><i>_</i><b>environment</b>
imported from non-Postfix processes.
<b>queue</b><i>_</i><b>directory</b>
- Top-level directory of the Postfix queue. This is
+ Top-level directory of the Postfix queue. This is
also the root directory of Postfix daemons that run
chrooted.
syslogd(8) system logging
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
--- /dev/null
+<html> <head> </head> <body> <pre>
+
+POSTQUEUE(1) POSTQUEUE(1)
+
+<b>NAME</b>
+ postqueue - Postfix queue control
+
+<b>SYNOPSIS</b>
+ <b>postqueue</b> <b>-f</b>
+ <b>postqueue</b> <b>-p</b>
+ <b>postqueue</b> <b>-s</b> <i>site</i>
+
+<b>DESCRIPTION</b>
+ The <b>postqueue</b> program implements the Postfix user inter-
+ face for queue management. It implements all the opera-
+ tions that are traditionally available via the <a href="sendmail.1.html"><b>sendmail</b>(1)</a>
+ command.
+
+ The following options are recognized:
+
+ <b>-f</b> Flush the queue: attempt to deliver all queued
+ mail.
+
+ This option implements the traditional <b>sendmail</b> <b>-q</b>
+ command, by contacting the Postfix <a href="qmgr.8.html"><b>qmgr</b>(8)</a> daemon.
+
+ <b>-p</b> Produce a traditional sendmail-style queue listing.
+
+ This option implements the traditional <b>mailq</b> com-
+ mand, by contacting the Postfix <a href="showq.8.html"><b>showq</b>(8)</a> daemon.
+
+ <b>-s</b> <i>site</i>
+ Schedule immediate delivery of all mail that is
+ queued for the named <i>site</i>. The site must be eligi-
+ ble for the "fast flush" service. See <a href="flushd.8.html"><b>flush</b>(8)</a> for
+ more information about the "fast flush" service.
+
+ This option implements the traditional <b>sendmail</b>
+ <b>-qR</b><i>site</i> command, by connecting to the SMTP server
+ at <b>$myhostname</b>.
+
+ <b>-v</b> Enable verbose logging for debugging purposes. Mul-
+ tiple <b>-v</b> options make the software increasingly
+ verbose.
+
+<b>SECURITY</b>
+ By design, this program is set-user (or group) id, so that
+ it can connect to public, but protected, Postfix daemon
+ processes.
+
+<b>DIAGNOSTICS</b>
+ Problems are logged to <b>syslogd</b>(8) and to the standard
+ error stream.
+
+<b>ENVIRONMENT</b>
+ The program deletes most environment information, because
+ the C library can't be trusted.
+
+<b>FILES</b>
+ /var/spool/postfix, mail queue
+ /etc/postfix, configuration files
+
+<b>CONFIGURATION</b> <b>PARAMETERS</b>
+ <b>import</b><i>_</i><b>environment</b>
+ List of names of environment parameters that can be
+ imported from non-Postfix processes.
+
+ <b>queue</b><i>_</i><b>directory</b>
+ Top-level directory of the Postfix queue. This is
+ also the root directory of Postfix daemons that run
+ chrooted.
+
+ <b>fast</b><i>_</i><b>flush</b><i>_</i><b>domains</b>
+ List of domains that will receive "fast flush" ser-
+ vice (default: all domains that this system is
+ willing to relay mail to). This list specifies the
+ domains that Postfix accepts in the SMTP <b>ETRN</b>
+ request and in the <b>sendmail</b> <b>-qR</b> command.
+
+<b>SEE</b> <b>ALSO</b>
+ sendmail(8) sendmail-compatible user interface
+ <a href="qmgr.8.html">qmgr(8)</a> queue manager
+ <a href="showq.8.html">showq(8)</a> list mail queue
+ <a href="flushd.8.html">flush(8)</a> fast flush service
+
+<b>LICENSE</b>
+ The Secure Mailer license must be distributed with this
+ software.
+
+<b>AUTHOR(S)</b>
+ Wietse Venema
+ IBM T.J. Watson Research
+ P.O. Box 704
+ Yorktown Heights, NY 10598, USA
+
+ 1
+
+</pre> </body> </html>
of a problem. This slows down run-away errors.
<b>SEE</b> <b>ALSO</b>
- http://cr.yp.to/proto/qmqp.html, QMQP protocol
+ <a href="http://cr.yp.to/proto/qmqp.html">http://cr.yp.to/proto/qmqp.html</a>, QMQP protocol
<a href="cleanup.8.html">cleanup(8)</a> message canonicalization
<a href="master.8.html">master(8)</a> process manager
syslogd(8) system logging
<ul>
<li>Mail is posted locally. The Postfix <a
-href="sendmail.1.html">sendmail</a> program deposits the message
-into the world-writable <b>maildrop</b> directory, where the message
-is picked up by the <a href="pickup.8.html">pickup</a> daemon.
-This daemon does some sanity checks, in order to protect the rest
-of the Postfix system. In order to avoid accidents, the directory
-permissions on the <b>maildrop</b> directory must be such that a
-user cannot delete someone elses mail.
+href="sendmail.1.html">sendmail</a> program invokes the privileged
+<a href="postdrop.1.html">postdrop</a> program which deposits the
+message into the <b>maildrop</b> directory, where the message is
+picked up by the <a href="pickup.8.html">pickup</a> daemon. This
+daemon does some sanity checks, in order to protect the rest of
+the Postfix system.
<p>
<p>
-By default, the <b>maildrop</b> queue directory is world-writable,
-so that local processes can submit mail without assistance from a
-set-uid or set-gid command or from a mail daemon process. The
-maildrop directory is not used for mail coming in via the network,
-and queue files are not readable for other users.
+Initially, the <b>maildrop</b> queue directory was world-writable,
+so that local processes could submit mail without assistance from
+a set-uid or set-gid command or from a mail daemon process. The
+maildrop directory was never used for mail coming in via the network,
+and its queue files were never not readable for other users.
<p>
<p>
-If a world-writable <b>maildrop</b> directory is not acceptable,
-sites can revoke world write permission, and enable <b>set-gid</b>
-privileges for a small helper program that is provided for this
-purpose.
+Because of the potential for misbehavior, Postfix has abandoned
+the world-writable <b>maildrop</b> directory, and uses a small
+set-gid <b>postdrop</b> helper program for mail submission.
<h2>Trust</h2>
By default, <b>sendmail</b> reads a message from standard input
until EOF or until it reads a line with only a <b>.</b> charac-
- ter, and arranges for delivery. <b>sendmail</b> attempts to cre-
- ate a queue file in the <b>maildrop</b> directory. If that direc-
- tory is not world-writable, the message is piped through
- the <a href="postdrop.1.html"><b>postdrop</b>(1)</a> command, which is expected to execute with
- suitable privileges.
+ ter, and arranges for delivery. <b>sendmail</b> relies on the
+ <a href="postdrop.1.html"><b>postdrop</b>(1)</a> command to create a queue file in the <b>maildrop</b>
+ directory.
Specific command aliases are provided for other common
modes of operation:
the recipients that still need to be delivered. If
mail could not be delivered upon the last attempt,
the reason for failure is shown. This mode of oper-
- ation is implemented by connecting to the <a href="showq.8.html"><b>showq</b>(8)</a>
- daemon.
+ ation is implemented by executing the <a href="postqueue.1.html"><b>postqueue</b>(1)</a>
+ command.
<b>newaliases</b>
Initialize the alias database. If no input file is
the message contains an <b>Errors-To:</b> message header.
<b>-q</b> Attempt to deliver all queued mail. This is imple-
- mented by kicking the <a href="qmgr.8.html"><b>qmgr</b>(8)</a> daemon.
+ mented by executing the <a href="postqueue.1.html"><b>postqueue</b>(1)</a> command.
<b>-q</b><i>interval</i> (ignored)
The interval between queue runs. Use the
Schedule immediate delivery of all mail that is
queued for the named <i>site</i>. This option accepts only
<i>site</i> names that are eligible for the "fast flush"
- service, and is implemented by connecting to the
- local SMTP server at <b>$myhostname</b>. See <a href="flushd.8.html"><b>flush</b>(8)</a> for
- more information about the "fast flush" service.
+ service, and is implemented by executing the
+ <a href="postqueue.1.html"><b>postqueue</b>(1)</a> command. See <a href="flushd.8.html"><b>flush</b>(8)</a> for more infor-
+ mation about the "fast flush" service.
<b>-qS</b><i>site</i>
This command is not implemented. Use the slower
<b>fast</b><i>_</i><b>flush</b><i>_</i><b>domains</b>
List of domains that will receive "fast flush" ser-
vice (default: all domains that this system is
- willing to relay mail to). This greatly improves
- the performance of the SMTP <b>ETRN</b> request, and of
- the <b>sendmail</b> <b>-qR</b> command. For domains not in the
- list, Postfix simply attempts to deliver all queued
- mail.
+ willing to relay mail to). This list specifies the
+ domains that Postfix accepts in the SMTP <b>ETRN</b>
+ request and in the <b>sendmail</b> <b>-qR</b> command.
<b>fork</b><i>_</i><b>attempts</b>
Number of attempts to <b>fork</b>() a process before giv-
<b>SEE</b> <b>ALSO</b>
<a href="pickup.8.html">pickup(8)</a> mail pickup daemon
<a href="postalias.1.html">postalias(1)</a> maintain alias database
- <a href="postdrop.1.html">postdrop(1)</a> privileged posting agent
+ <a href="postdrop.1.html">postdrop(1)</a> mail posting utility
<a href="postfix.1.html">postfix(1)</a> mail system control
- <a href="postkick.1.html">postkick(1)</a> kick a Postfix daemon
+ <a href="postqueue.1.html">postqueue(1)</a> mail queue control
<a href="qmgr.8.html">qmgr(8)</a> queue manager
- <a href="showq.8.html">showq(8)</a> list mail queue
<a href="smtpd.8.html">smtpd(8)</a> SMTP server
- flushd(8) fast flush service
+ <a href="flushd.8.html">flush(8)</a> fast flush service
syslogd(8) system logging
<b>LICENSE</b>
COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.1 \
man1/postkick.1 man1/postlock.1 man1/postlog.1 man1/postdrop.1 \
man1/postmap.1 man1/sendmail.1 man1/mailq.1 man1/newaliases.1 \
- man1/postsuper.1
+ man1/postqueue.1 man1/postsuper.1
CONFIG = man5/access.5 man5/aliases.5 man5/canonical.5 man5/relocated.5 \
man5/transport.5 man5/virtual.5 man5/pcre_table.5 man5/regexp_table.5
man1/postmap.1: ../src/postmap/postmap.c
../mantools/srctoman $? >$@
+man1/postqueue.1: ../src/postqueue/postqueue.c
+ ../mantools/srctoman $? >$@
+
man1/postsuper.1: ../src/postsuper/postsuper.c
../mantools/srctoman $? >$@
.SH NAME
postdrop
\-
-Postfix mail posting agent
+Postfix mail posting utility
.SH SYNOPSIS
.na
.nf
The \fBpostdrop\fR command creates a file in the \fBmaildrop\fR
directory and copies its standard input to the file.
-The command is designed to run with set-gid privileges, and with
-group write permission to the \fBmaildrop\fR queue directory.
-
-The \fBpostdrop\fR command is automatically invoked by the
-\fBsendmail\fR(1) mail posting agent when the \fBmaildrop\fR
-queue directory is not world-writable.
-
Options:
.IP \fB-v\fR
Enable verbose logging for debugging purposes. Multiple \fB-v\fR
.nf
.ad
.fi
-This program is designed so that it can run with set-user (or
-group) id privileges.
+The command is designed to run with set-gid privileges, and with
+group write permission to the \fBmaildrop\fR queue directory.
.SH DIAGNOSTICS
.ad
.fi
.nf
.ad
.fi
-The program deletes all environment information, because the C
+The program deletes most environment information, because the C
library can't be trusted.
.SH FILES
.na
--- /dev/null
+.TH POSTQUEUE 1
+.ad
+.fi
+.SH NAME
+postqueue
+\-
+Postfix queue control
+.SH SYNOPSIS
+.na
+.nf
+\fBpostqueue\fR \fB-f\fR
+.br
+\fBpostqueue\fR \fB-p\fR
+.br
+\fBpostqueue\fR \fB-s \fIsite\fR
+.SH DESCRIPTION
+.ad
+.fi
+The \fBpostqueue\fR program implements the Postfix user interface
+for queue management. It implements all the operations that are
+traditionally available via the \fBsendmail\fR(1) command.
+
+The following options are recognized:
+.IP \fB-f\fR
+Flush the queue: attempt to deliver all queued mail.
+
+This option implements the traditional \fBsendmail -q\fR command,
+by contacting the Postfix \fBqmgr\fR(8) daemon.
+.IP \fB-p\fR
+Produce a traditional sendmail-style queue listing.
+
+This option implements the traditional \fBmailq\fR command,
+by contacting the Postfix \fBshowq\fR(8) daemon.
+.IP "\fB-s \fIsite\fR"
+Schedule immediate delivery of all mail that is queued for the named
+\fIsite\fR. The site must be eligible for the "fast flush" service.
+See \fBflush\fR(8) for more information about the "fast flush"
+service.
+
+This option implements the traditional \fBsendmail -qR\fIsite\fR
+command, by connecting to the SMTP server at \fB$myhostname\fR.
+.IP \fB-v\fR
+Enable verbose logging for debugging purposes. Multiple \fB-v\fR
+options make the software increasingly verbose.
+.SH SECURITY
+.na
+.nf
+.ad
+.fi
+By design, this program is set-user (or group) id, so that it
+can connect to public, but protected, Postfix daemon processes.
+.SH DIAGNOSTICS
+.ad
+.fi
+Problems are logged to \fBsyslogd\fR(8) and to the standard error
+stream.
+.SH ENVIRONMENT
+.na
+.nf
+.ad
+.fi
+The program deletes most environment information, because the C
+library can't be trusted.
+.SH FILES
+.na
+.nf
+/var/spool/postfix, mail queue
+/etc/postfix, configuration files
+.SH CONFIGURATION PARAMETERS
+.na
+.nf
+.ad
+.fi
+.IP \fBimport_environment\fR
+List of names of environment parameters that can be imported
+from non-Postfix processes.
+.IP \fBqueue_directory\fR
+Top-level directory of the Postfix queue. This is also the root
+directory of Postfix daemons that run chrooted.
+.IP \fBfast_flush_domains\fR
+List of domains that will receive "fast flush" service (default: all
+domains that this system is willing to relay mail to). This list
+specifies the domains that Postfix accepts in the SMTP \fBETRN\fR
+request and in the \fBsendmail -qR\fR command.
+.SH SEE ALSO
+.na
+.nf
+sendmail(8) sendmail-compatible user interface
+qmgr(8) queue manager
+showq(8) list mail queue
+flush(8) fast flush service
+.SH LICENSE
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH AUTHOR(S)
+.na
+.nf
+Wietse Venema
+IBM T.J. Watson Research
+P.O. Box 704
+Yorktown Heights, NY 10598, USA
By default, \fBsendmail\fR reads a message from standard input
until EOF or until it reads a line with only a \fB.\fR character,
-and arranges for delivery. \fBsendmail\fR attempts to create
-a queue file in the \fBmaildrop\fR directory. If that directory
-is not world-writable, the message is piped through the
-\fBpostdrop\fR(1) command, which is expected to execute with
-suitable privileges.
+and arranges for delivery. \fBsendmail\fR relies on the
+\fBpostdrop\fR(1) command to create a queue file in the \fBmaildrop\fR
+directory.
Specific command aliases are provided for other common modes of
operation:
size, arrival time, sender, and the recipients that still need to
be delivered. If mail could not be delivered upon the last attempt,
the reason for failure is shown. This mode of operation is implemented
-by connecting to the \fBshowq\fR(8) daemon.
+by executing the \fBpostqueue\fR(1) command.
.IP \fBnewaliases\fR
Initialize the alias database. If no input file is specified (with
the \fB-oA\fR option, see below), the program processes the file(s)
delivery problems are sent to, unless the message contains an
\fBErrors-To:\fR message header.
.IP \fB-q\fR
-Attempt to deliver all queued mail. This is implemented by kicking the
-\fBqmgr\fR(8) daemon.
+Attempt to deliver all queued mail. This is implemented by
+executing the \fBpostqueue\fR(1) command.
.IP "\fB-q\fIinterval\fR (ignored)"
The interval between queue runs. Use the \fBqueue_run_delay\fR
configuration parameter instead.
Schedule immediate delivery of all mail that is queued for the named
\fIsite\fR. This option accepts only \fIsite\fR names that are
eligible for the "fast flush" service, and is implemented by
-connecting to the local SMTP server at \fB$myhostname\fR.
+executing the \fBpostqueue\fR(1) command.
See \fBflush\fR(8) for more information about the "fast flush"
service.
.IP \fB-qS\fIsite\fR
command line option is specified without delimiter characters.
.IP \fBfast_flush_domains\fR
List of domains that will receive "fast flush" service (default: all
-domains that this system is willing to relay mail to). This greatly
-improves the performance of the SMTP \fBETRN\fR request, and of the
-\fBsendmail -qR\fR command. For domains not in the list, Postfix simply
-attempts to deliver all queued mail.
+domains that this system is willing to relay mail to). This list
+specifies the domains that Postfix accepts in the SMTP \fBETRN\fR
+request and in the \fBsendmail -qR\fR command.
.IP \fBfork_attempts\fR
Number of attempts to \fBfork\fR() a process before giving up.
.IP \fBfork_delay\fR
.nf
pickup(8) mail pickup daemon
postalias(1) maintain alias database
-postdrop(1) privileged posting agent
+postdrop(1) mail posting utility
postfix(1) mail system control
-postkick(1) kick a Postfix daemon
+postqueue(1) mail queue control
qmgr(8) queue manager
-showq(8) list mail queue
smtpd(8) SMTP server
-flushd(8) fast flush service
+flush(8) fast flush service
syslogd(8) system logging
.SH LICENSE
.na
s/[<bB>]*postlock[</bB>]*(1)/<a href="postlock.1.html">&<\/a>/
s/[<bB>]*postlog[</bB>]*(1)/<a href="postlog.1.html">&<\/a>/
s/[<bB>]*postmap[</bB>]*(1)/<a href="postmap.1.html">&<\/a>/
+ s/[<bB>]*postqueue[</bB>]*(1)/<a href="postqueue.1.html">&<\/a>/
+ s/[<bB>]*postsuper[</bB>]*(1)/<a href="postsuper.1.html">&<\/a>/
s/[<bB>]*send[-</bB>]*\n*[ <bB>]*mail[</bB>]*(1)/<a href="sendmail.1.html">&<\/a>/
s/[<bB>]*access[</bB>]*(5)/<a href="access.5.html">&<\/a>/
s/[<bB>]*aliases[</bB>]*(5)/<a href="aliases.5.html">&<\/a>/
* that the runtime error handler can clean up in case of problems.
*/
state->handle = mail_stream_file(MAIL_QUEUE_INCOMING,
- MAIL_CLASS_PUBLIC, MAIL_SERVICE_QUEUE);
+ MAIL_CLASS_PUBLIC, MAIL_SERVICE_QUEUE, 0);
state->dst = state->handle->stream;
cleanup_path = mystrdup(VSTREAM_PATH(state->dst));
state->queue_id = mystrdup(state->handle->id);
/* .in -4
/* } MAIL_STREAM;
/*
-/* MAIL_STREAM *mail_stream_file(queue, class, service)
+/* MAIL_STREAM *mail_stream_file(queue, class, service, mode)
/* const char *queue;
/* const char *class;
/* const char *service;
+/* int mode;
/*
/* MAIL_STREAM *mail_stream_service(class, service)
/* const char *class;
/*
/* mail_stream_file() opens a mail stream to a newly-created file and
/* arranges for trigger delivery at finish time. This call never fails.
-/* But it may take forever.
+/* But it may take forever. The mode argument specifies additional
+/* file permissions that will be OR-ed in.
/*
/* mail_stream_command() opens a mail stream to external command,
/* and receives queue ID information from the command. The result
* END record are discarded.
*/
if (vstream_fflush(info->stream)
- || fchmod(vstream_fileno(info->stream), 0700)
+ || fchmod(vstream_fileno(info->stream), 0700 | info->mode)
#ifdef HAS_FSYNC
|| fsync(vstream_fileno(info->stream))
#endif
/* mail_stream_file - destination is file */
MAIL_STREAM *mail_stream_file(const char *queue, const char *class,
- const char *service)
+ const char *service, int mode)
{
MAIL_STREAM *info;
VSTREAM *stream;
- stream = mail_queue_enter(queue, 0600);
+ stream = mail_queue_enter(queue, 0600 | mode);
if (msg_verbose)
msg_info("open %s", VSTREAM_PATH(stream));
info->id = mystrdup(basename(VSTREAM_PATH(stream)));
info->class = mystrdup(class);
info->service = mystrdup(service);
+ info->mode = mode;
return (info);
}
MAIL_STREAM_CLOSE_FN close; /* close stream */
char *class; /* trigger class */
char *service; /* trigger service */
+ int mode; /* additional permissions */
};
-extern MAIL_STREAM *mail_stream_file(const char *, const char *, const char *);
+extern MAIL_STREAM *mail_stream_file(const char *, const char *, const char *, int);
extern MAIL_STREAM *mail_stream_service(const char *, const char *);
extern MAIL_STREAM *mail_stream_command(const char *);
extern void mail_stream_cleanup(MAIL_STREAM *);
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-20011226"
+#define DEF_MAIL_VERSION "Snapshot-20011230"
extern char *var_mail_version;
/* LICENSE
{
VSTREAM *stream;
- stream = mail_connect_wait(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
+ stream = mail_connect_wait(MAIL_CLASS_PUBLIC, MAIL_SERVICE_CLEANUP);
post_mail_init(stream, sender, recipient, flags);
return (stream);
}
{
VSTREAM *stream;
- if ((stream = mail_connect(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP,
+ if ((stream = mail_connect(MAIL_CLASS_PUBLIC, MAIL_SERVICE_CLEANUP,
BLOCKING)) != 0)
post_mail_init(stream, sender, recipient, flags);
return (stream);
* "message too large", perhaps some others. The reason not to bounce
* ourselves is that we don't really know who the recipients are.
*/
- cleanup = mail_connect(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP, BLOCKING);
+ cleanup = mail_connect(MAIL_CLASS_PUBLIC, MAIL_SERVICE_CLEANUP, BLOCKING);
if (cleanup == 0)
return (0);
close_on_exec(vstream_fileno(cleanup), CLOSE_ON_EXEC);
pickup.o: ../../include/vstring.h
pickup.o: ../../include/vbuf.h
pickup.o: ../../include/vstream.h
-pickup.o: ../../include/open_as.h
-pickup.o: ../../include/set_eugid.h
+pickup.o: ../../include/set_ugid.h
+pickup.o: ../../include/safe_open.h
pickup.o: ../../include/mail_queue.h
pickup.o: ../../include/mail_open_ok.h
pickup.o: ../../include/mymalloc.h
#include <scan_dir.h>
#include <vstring.h>
#include <vstream.h>
-#include <open_as.h>
-#include <set_eugid.h>
+#include <set_ugid.h>
+#include <safe_open.h>
/* Global library. */
static int pickup_file(PICKUP_INFO *info)
{
- struct stat st;
- VSTRING *buf;
+ VSTRING *buf = vstring_alloc(100);
int status;
VSTREAM *qfile;
VSTREAM *cleanup;
* Perhaps we should save "bad" files elsewhere for further inspection.
* XXX How can we delete a file when open() fails with ENOENT?
*/
- fd = open_as(info->path, O_RDONLY | O_NONBLOCK, 0,
- info->st.st_uid, info->st.st_gid);
- if (fd < 0) {
+ qfile = safe_open(info->path, O_RDONLY | O_NONBLOCK, 0,
+ (struct stat *) 0, -1, -1, buf);
+ if (qfile == 0) {
if (errno != ENOENT)
- msg_fatal("open input file %s: %m", info->path);
- msg_warn("open input file %s: %m", info->path);
- return (REMOVE_MESSAGE_FILE);
+ msg_warn("open input file %s: %s", info->path, vstring_str(buf));
+ vstring_free(buf);
+ return (errno == EACCES ? KEEP_MESSAGE_FILE : REMOVE_MESSAGE_FILE);
}
- /*
- * Like safe_open(pat, O_RDONLY, 0), but without any link count checks.
- */
- if (fstat(fd, &st) < 0)
- msg_fatal("fstat: %m");
- if (st.st_dev != info->st.st_dev
- || st.st_ino != info->st.st_ino
- || st.st_mode != info->st.st_mode) {
- msg_warn("%s: uid %ld: file has changed", info->path, (long) st.st_uid);
- return (REMOVE_MESSAGE_FILE);
- }
- qfile = vstream_fdopen(fd, O_RDONLY);
-
/*
* Contact the cleanup service and read the queue ID that it has
* allocated. In case of trouble, request that the cleanup service
*/
#define PICKUP_CLEANUP_FLAGS (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_FILTER)
- buf = vstring_alloc(100);
- cleanup = mail_connect_wait(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
+ cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, MAIL_SERVICE_CLEANUP);
if (attr_scan(cleanup, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, buf,
ATTR_TYPE_END) != 1
} while (file_count);
}
-/* drop_privileges - drop privileges most of the time */
+/* drop_privileges - drop privileges */
static void drop_privileges(char *unused_name, char **unused_argv)
{
- set_eugid(var_owner_uid, var_owner_gid);
+
+ /*
+ * In case master.cf was not updated for unprivileged service.
+ */
+ if (getuid() != var_owner_uid)
+ set_ugid(var_owner_uid, var_owner_gid);
}
/* main - pass control to the multi-threaded server skeleton */
postconf.o: ../../include/safe.h
postconf.o: ../../include/mymalloc.h
postconf.o: ../../include/split_at.h
-postconf.o: ../../include/readlline.h
+postconf.o: ../../include/vstring_vstream.h
postconf.o: ../../include/myflock.h
postconf.o: ../../include/mynetworks.h
postconf.o: ../../include/mail_conf.h
/* NAME
/* postdrop 1
/* SUMMARY
-/* Postfix mail posting agent
+/* Postfix mail posting utility
/* SYNOPSIS
/* \fBpostdrop\fR [\fIoption ...\fR]
/* DESCRIPTION
/* The \fBpostdrop\fR command creates a file in the \fBmaildrop\fR
/* directory and copies its standard input to the file.
/*
-/* The command is designed to run with set-gid privileges, and with
-/* group write permission to the \fBmaildrop\fR queue directory.
-/*
-/* The \fBpostdrop\fR command is automatically invoked by the
-/* \fBsendmail\fR(1) mail posting agent when the \fBmaildrop\fR
-/* queue directory is not world-writable.
-/*
/* Options:
/* .IP \fB-v\fR
/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
/* SECURITY
/* .ad
/* .fi
-/* This program is designed so that it can run with set-user (or
-/* group) id privileges.
+/* The command is designed to run with set-gid privileges, and with
+/* group write permission to the \fBmaildrop\fR queue directory.
/* DIAGNOSTICS
/* Fatal errors: malformed input, I/O error, out of memory. Problems
/* are logged to \fBsyslogd\fR(8) and to the standard error stream.
/* ENVIRONMENT
/* .ad
/* .fi
-/* The program deletes all environment information, because the C
+/* The program deletes most environment information, because the C
/* library can't be trusted.
/* FILES
/* /var/spool/postfix, mail queue
static void postdrop_sig(int sig)
{
- signal(SIGHUP, SIG_IGN);
- signal(SIGINT, SIG_IGN);
- signal(SIGQUIT, SIG_IGN);
- signal(SIGTERM, SIG_IGN);
- postdrop_cleanup();
- exit(sig);
+
+ /*
+ * Assume atomic signal() updates, even when emulated with sigaction().
+ */
+ if (signal(SIGHUP, SIG_IGN) != SIG_IGN
+ && signal(SIGINT, SIG_IGN) != SIG_IGN
+ && signal(SIGQUIT, SIG_IGN) != SIG_IGN
+ && signal(SIGTERM, SIG_IGN) != SIG_IGN) {
+ postdrop_cleanup();
+ exit(sig);
+ }
}
/* main - the main program */
* clean up in case of a fatal error or an interrupt.
*/
dst = mail_stream_file(MAIL_QUEUE_MAILDROP, MAIL_CLASS_PUBLIC,
- MAIL_SERVICE_PICKUP);
+ MAIL_SERVICE_PICKUP, 0444);
attr_print(VSTREAM_OUT, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, dst->id,
ATTR_TYPE_END);
--- /dev/null
+SHELL = /bin/sh
+SRCS = postqueue.c
+OBJS = postqueue.o
+HDRS =
+TESTSRC =
+WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
+ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
+ -Wunused
+DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+TESTPROG=
+PROG = postqueue
+INC_DIR = ../../include
+LIBS = ../../lib/libglobal.a ../../lib/libutil.a
+
+.c.o:; $(CC) $(CFLAGS) -c $*.c
+
+$(PROG): $(OBJS) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+
+Makefile: Makefile.in
+ (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+
+test: $(TESTPROG)
+
+update: ../../bin/$(PROG)
+
+../../bin/$(PROG): $(PROG)
+ cp $(PROG) ../../bin
+
+printfck: $(OBJS) $(PROG)
+ rm -rf printfck
+ mkdir printfck
+ sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
+ set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
+ cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
+
+lint:
+ lint $(DEFS) $(SRCS) $(LINTFIX)
+
+clean:
+ rm -f *.o *core $(PROG) $(TESTPROG) junk
+ rm -rf printfck
+
+tidy: clean
+
+depend: $(MAKES)
+ (sed '1,/^# do not edit/!d' Makefile.in; \
+ set -e; for i in [a-z][a-z0-9]*.c; do \
+ $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
+ -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
+ done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
+ @$(EXPORT) make -f Makefile.in Makefile 1>&2
+
+# do not edit below this line - it is generated by 'make depend'
+postqueue.o: postqueue.c
+postqueue.o: ../../include/sys_defs.h
+postqueue.o: ../../include/msg.h
+postqueue.o: ../../include/mymalloc.h
+postqueue.o: ../../include/clean_env.h
+postqueue.o: ../../include/vstream.h
+postqueue.o: ../../include/vbuf.h
+postqueue.o: ../../include/msg_vstream.h
+postqueue.o: ../../include/msg_syslog.h
+postqueue.o: ../../include/argv.h
+postqueue.o: ../../include/safe.h
+postqueue.o: ../../include/connect.h
+postqueue.o: ../../include/iostuff.h
+postqueue.o: ../../include/mail_proto.h
+postqueue.o: ../../include/attr.h
+postqueue.o: ../../include/mail_params.h
+postqueue.o: ../../include/mail_conf.h
+postqueue.o: ../../include/mail_task.h
+postqueue.o: ../../include/debug_process.h
+postqueue.o: ../../include/mail_run.h
+postqueue.o: ../../include/mail_flush.h
+postqueue.o: ../../include/smtp_stream.h
+postqueue.o: ../../include/vstring.h
--- /dev/null
+/*++
+/* NAME
+/* postqueue 1
+/* SUMMARY
+/* Postfix queue control
+/* SYNOPSIS
+/* \fBpostqueue\fR \fB-f\fR
+/* .br
+/* \fBpostqueue\fR \fB-p\fR
+/* .br
+/* \fBpostqueue\fR \fB-s \fIsite\fR
+/* DESCRIPTION
+/* The \fBpostqueue\fR program implements the Postfix user interface
+/* for queue management. It implements all the operations that are
+/* traditionally available via the \fBsendmail\fR(1) command.
+/*
+/* The following options are recognized:
+/* .IP \fB-f\fR
+/* Flush the queue: attempt to deliver all queued mail.
+/*
+/* This option implements the traditional \fBsendmail -q\fR command,
+/* by contacting the Postfix \fBqmgr\fR(8) daemon.
+/* .IP \fB-p\fR
+/* Produce a traditional sendmail-style queue listing.
+/*
+/* This option implements the traditional \fBmailq\fR command,
+/* by contacting the Postfix \fBshowq\fR(8) daemon.
+/* .IP "\fB-s \fIsite\fR"
+/* Schedule immediate delivery of all mail that is queued for the named
+/* \fIsite\fR. The site must be eligible for the "fast flush" service.
+/* See \fBflush\fR(8) for more information about the "fast flush"
+/* service.
+/*
+/* This option implements the traditional \fBsendmail -qR\fIsite\fR
+/* command, by connecting to the SMTP server at \fB$myhostname\fR.
+/* .IP \fB-v\fR
+/* Enable verbose logging for debugging purposes. Multiple \fB-v\fR
+/* options make the software increasingly verbose.
+/* SECURITY
+/* .ad
+/* .fi
+/* By design, this program is set-user (or group) id, so that it
+/* can connect to public, but protected, Postfix daemon processes.
+/* DIAGNOSTICS
+/* Problems are logged to \fBsyslogd\fR(8) and to the standard error
+/* stream.
+/* ENVIRONMENT
+/* .ad
+/* .fi
+/* The program deletes most environment information, because the C
+/* library can't be trusted.
+/* FILES
+/* /var/spool/postfix, mail queue
+/* /etc/postfix, configuration files
+/* CONFIGURATION PARAMETERS
+/* .ad
+/* .fi
+/* .IP \fBimport_environment\fR
+/* List of names of environment parameters that can be imported
+/* from non-Postfix processes.
+/* .IP \fBqueue_directory\fR
+/* Top-level directory of the Postfix queue. This is also the root
+/* directory of Postfix daemons that run chrooted.
+/* .IP \fBfast_flush_domains\fR
+/* List of domains that will receive "fast flush" service (default: all
+/* domains that this system is willing to relay mail to). This list
+/* specifies the domains that Postfix accepts in the SMTP \fBETRN\fR
+/* request and in the \fBsendmail -qR\fR command.
+/* SEE ALSO
+/* sendmail(8) sendmail-compatible user interface
+/* qmgr(8) queue manager
+/* showq(8) list mail queue
+/* flush(8) fast flush service
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <sysexits.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <clean_env.h>
+#include <vstream.h>
+#include <msg_vstream.h>
+#include <msg_syslog.h>
+#include <argv.h>
+#include <safe.h>
+#include <connect.h>
+
+/* Global library. */
+
+#include <mail_proto.h>
+#include <mail_params.h>
+#include <mail_conf.h>
+#include <mail_task.h>
+#include <debug_process.h>
+#include <mail_run.h>
+#include <mail_flush.h>
+#include <smtp_stream.h>
+
+/* Application-specific. */
+
+ /*
+ * Modes of operation.
+ */
+#define PQ_MODE_DEFAULT 0 /* noop */
+#define PQ_MODE_MAILQ_LIST 1 /* list mail queue */
+#define PQ_MODE_FLUSH_QUEUE 2 /* flush queue */
+#define PQ_MODE_FLUSH_SITE 3 /* flush site */
+
+ /*
+ * Error handlers.
+ */
+static void postqueue_cleanup(void);
+static NORETURN PRINTFLIKE(2, 3) fatal_error(int, const char *,...);
+
+ /*
+ * Silly little macros (SLMs).
+ */
+#define STR vstring_str
+
+/* show_queue - show queue status */
+
+static void show_queue(void)
+{
+ char buf[VSTREAM_BUFSIZE];
+ VSTREAM *showq;
+ int n;
+
+ /*
+ * Connect to the show queue service. Terminate silently when piping into
+ * a program that terminates early.
+ */
+ if ((showq = mail_connect(MAIL_CLASS_PUBLIC, MAIL_SERVICE_SHOWQ, BLOCKING)) != 0) {
+ while ((n = vstream_fread(showq, buf, sizeof(buf))) > 0)
+ if (vstream_fwrite(VSTREAM_OUT, buf, n) != n
+ || vstream_fflush(VSTREAM_OUT) != 0)
+ msg_fatal("write error: %m");
+
+ if (vstream_fclose(showq))
+ msg_warn("close: %m");
+ }
+
+ /*
+ * When the mail system is down, the superuser can still access the queue
+ * directly. Just run the showq program in stand-alone mode.
+ */
+ else if (geteuid() == 0) {
+ ARGV *argv;
+ int stat;
+
+ msg_warn("Mail system is down -- accessing queue directly");
+ argv = argv_alloc(6);
+ argv_add(argv, MAIL_SERVICE_SHOWQ, "-c", "-u", "-S", (char *) 0);
+ for (n = 0; n < msg_verbose; n++)
+ argv_add(argv, "-v", (char *) 0);
+ argv_terminate(argv);
+ stat = mail_run_foreground(var_daemon_dir, argv->argv);
+ argv_free(argv);
+ }
+
+ /*
+ * When the mail system is down, unprivileged users are stuck, because by
+ * design the mail system contains no set_uid programs. The only way for
+ * an unprivileged user to cross protection boundaries is to talk to the
+ * showq daemon.
+ */
+ else {
+ fatal_error(EX_UNAVAILABLE,
+ "Queue report unavailable - mail system is down");
+ }
+}
+
+/* flush_queue - force delivery */
+
+static void flush_queue(void)
+{
+
+ /*
+ * Trigger the flush queue service.
+ */
+ if (mail_flush_deferred() < 0)
+ fatal_error(EX_UNAVAILABLE,
+ "Cannot flush mail queue - mail system is down");
+}
+
+/* chat - send command and examine reply */
+
+static void chat(VSTREAM * fp, VSTRING * buf, const char *fmt,...)
+{
+ va_list ap;
+
+ smtp_get(buf, fp, var_line_limit);
+ if (STR(buf)[0] != '2')
+ fatal_error(EX_UNAVAILABLE, "server rejected ETRN request: %s",
+ STR(buf));
+
+ if (msg_verbose)
+ msg_info("<<< %s", STR(buf));
+
+ if (msg_verbose) {
+ va_start(ap, fmt);
+ vstring_vsprintf(buf, fmt, ap);
+ va_end(ap);
+ msg_info(">>> %s", STR(buf));
+ }
+ va_start(ap, fmt);
+ smtp_vprintf(fp, fmt, ap);
+ va_end(ap);
+}
+
+/* flush_site - flush mail for site */
+
+static void flush_site(const char *site)
+{
+ VSTRING *buf = vstring_alloc(10);
+ VSTREAM *fp;
+ int sock;
+ int status;
+
+ /*
+ * Make connection to the local SMTP server. Translate "connection
+ * refused" into something less misleading.
+ */
+ vstring_sprintf(buf, "%s:smtp", var_myhostname);
+ if ((sock = inet_connect(STR(buf), BLOCKING, 10)) < 0) {
+ if (errno == ECONNREFUSED)
+ fatal_error(EX_UNAVAILABLE, "mail service at %s is down",
+ var_myhostname);
+ fatal_error(EX_UNAVAILABLE, "connect to mail service at %s: %m",
+ var_myhostname);
+ }
+ fp = vstream_fdopen(sock, O_RDWR);
+
+ /*
+ * Prepare for trouble.
+ */
+ vstream_control(fp, VSTREAM_CTL_EXCEPT, VSTREAM_CTL_END);
+ status = vstream_setjmp(fp);
+ if (status != 0) {
+ switch (status) {
+ case SMTP_ERR_EOF:
+ fatal_error(EX_UNAVAILABLE, "server at %s aborted connection",
+ var_myhostname);
+ case SMTP_ERR_TIME:
+ fatal_error(EX_IOERR,
+ "timeout while talking to server at %s", var_myhostname);
+ }
+ }
+ smtp_timeout_setup(fp, 60);
+
+ /*
+ * Chat with the SMTP server.
+ */
+ chat(fp, buf, "helo %s", var_myhostname);
+ chat(fp, buf, "etrn %s", site);
+ chat(fp, buf, "quit");
+
+ vstream_fclose(fp);
+ vstring_free(buf);
+}
+
+static int fatal_status;
+
+/* postqueue_cleanup - callback for the runtime error handler */
+
+static NORETURN postqueue_cleanup(void)
+{
+ exit(fatal_status > 0 ? fatal_status : 1);
+}
+
+/* fatal_error - give up and notify parent */
+
+static void fatal_error(int status, const char *fmt,...)
+{
+ VSTRING *text = vstring_alloc(10);
+ va_list ap;
+
+ fatal_status = status;
+ va_start(ap, fmt);
+ vstring_vsprintf(text, fmt, ap);
+ va_end(ap);
+ msg_fatal("%s", vstring_str(text));
+}
+
+/* main - the main program */
+
+int main(int argc, char **argv)
+{
+ struct stat st;
+ char *slash;
+ int c;
+ int fd;
+ int mode = PQ_MODE_DEFAULT;
+ int debug_me = 0;
+ char *site_to_flush = 0;
+ ARGV *import_env;
+
+ /*
+ * Be consistent with file permissions.
+ */
+ umask(022);
+
+ /*
+ * To minimize confusion, make sure that the standard file descriptors
+ * are open before opening anything else. XXX Work around for 44BSD where
+ * fstat can return EBADF on an open file descriptor.
+ */
+ for (fd = 0; fd < 3; fd++)
+ if (fstat(fd, &st) == -1
+ && (close(fd), open("/dev/null", O_RDWR, 0)) != fd)
+ fatal_error(EX_UNAVAILABLE, "open /dev/null: %m");
+
+ /*
+ * Initialize. Set up logging, read the global configuration file and
+ * extract configuration information. Set up signal handlers so that we
+ * can clean up incomplete output.
+ */
+ if ((slash = strrchr(argv[0], '/')) != 0)
+ argv[0] = slash + 1;
+ msg_vstream_init(argv[0], VSTREAM_ERR);
+ msg_syslog_init(mail_task("postqueue"), LOG_PID, LOG_FACILITY);
+ set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0]));
+
+ /*
+ * Further initialization...
+ */
+ mail_conf_read();
+
+ /*
+ * Strip the environment so we don't have to trust the C library.
+ */
+ import_env = argv_split(var_import_environ, ", \t\r\n");
+ clean_env(import_env->argv);
+ argv_free(import_env);
+
+ if (chdir(var_queue_dir))
+ fatal_error(EX_UNAVAILABLE, "chdir %s: %m", var_queue_dir);
+
+ signal(SIGPIPE, SIG_IGN);
+ msg_cleanup(postqueue_cleanup);
+
+ /*
+ * Parse JCL.
+ */
+ while ((c = GETOPT(argc, argv, "fps:v")) > 0) {
+ switch (c) {
+ case 'f': /* flush queue */
+ mode = PQ_MODE_FLUSH_QUEUE;
+ break;
+ case 'p': /* traditional mailq */
+ mode = PQ_MODE_MAILQ_LIST;
+ break;
+ break;
+ case 's': /* flush site */
+ mode = PQ_MODE_FLUSH_SITE;
+ site_to_flush = optarg;
+ break;
+ case 'v':
+ msg_verbose++;
+ break;
+ default:
+ fatal_error(EX_USAGE, "usage: %s -[fpsv]", argv[0]);
+ }
+ }
+
+ /*
+ * Start processing.
+ */
+ switch (mode) {
+ default:
+ msg_panic("unknown operation mode: %d", mode);
+ /* NOTREACHED */
+ case PQ_MODE_MAILQ_LIST:
+ show_queue();
+ exit(0);
+ break;
+ case PQ_MODE_FLUSH_SITE:
+ flush_site(site_to_flush);
+ exit(0);
+ break;
+ case PQ_MODE_FLUSH_QUEUE:
+ flush_queue();
+ exit(0);
+ break;
+ case PQ_MODE_DEFAULT:
+ fatal_error(EX_USAGE, "usage: %s -[fpsv]", argv[0]);
+ break;
+ }
+}
/*
* Connect to the cleanup server. Log client name/address with queue ID.
*/
- state->dest = mail_stream_service(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
+ state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, MAIL_SERVICE_CLEANUP);
if (state->dest == 0
|| attr_print(state->dest->stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER,
ATTR_TYPE_END) != 0)
msg_fatal("unable to connect to the %s %s service",
- MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
+ MAIL_CLASS_PUBLIC, MAIL_SERVICE_CLEANUP);
state->cleanup = state->dest->stream;
state->queue_id = mystrdup(state->dest->id);
msg_info("%s: client=%s", state->queue_id, state->namaddr);
sendmail.o: ../../include/resolve_clnt.h
sendmail.o: ../../include/mail_flush.h
sendmail.o: ../../include/mail_stream.h
-sendmail.o: ../../include/smtp_stream.h
sendmail.o: ../../include/verp_sender.h
/*
/* By default, \fBsendmail\fR reads a message from standard input
/* until EOF or until it reads a line with only a \fB.\fR character,
-/* and arranges for delivery. \fBsendmail\fR attempts to create
-/* a queue file in the \fBmaildrop\fR directory. If that directory
-/* is not world-writable, the message is piped through the
-/* \fBpostdrop\fR(1) command, which is expected to execute with
-/* suitable privileges.
+/* and arranges for delivery. \fBsendmail\fR relies on the
+/* \fBpostdrop\fR(1) command to create a queue file in the \fBmaildrop\fR
+/* directory.
/*
/* Specific command aliases are provided for other common modes of
/* operation:
/* size, arrival time, sender, and the recipients that still need to
/* be delivered. If mail could not be delivered upon the last attempt,
/* the reason for failure is shown. This mode of operation is implemented
-/* by connecting to the \fBshowq\fR(8) daemon.
+/* by executing the \fBpostqueue\fR(1) command.
/* .IP \fBnewaliases\fR
/* Initialize the alias database. If no input file is specified (with
/* the \fB-oA\fR option, see below), the program processes the file(s)
/* delivery problems are sent to, unless the message contains an
/* \fBErrors-To:\fR message header.
/* .IP \fB-q\fR
-/* Attempt to deliver all queued mail. This is implemented by kicking the
-/* \fBqmgr\fR(8) daemon.
+/* Attempt to deliver all queued mail. This is implemented by
+/* executing the \fBpostqueue\fR(1) command.
/* .IP "\fB-q\fIinterval\fR (ignored)"
/* The interval between queue runs. Use the \fBqueue_run_delay\fR
/* configuration parameter instead.
/* Schedule immediate delivery of all mail that is queued for the named
/* \fIsite\fR. This option accepts only \fIsite\fR names that are
/* eligible for the "fast flush" service, and is implemented by
-/* connecting to the local SMTP server at \fB$myhostname\fR.
+/* executing the \fBpostqueue\fR(1) command.
/* See \fBflush\fR(8) for more information about the "fast flush"
/* service.
/* .IP \fB-qS\fIsite\fR
/* command line option is specified without delimiter characters.
/* .IP \fBfast_flush_domains\fR
/* List of domains that will receive "fast flush" service (default: all
-/* domains that this system is willing to relay mail to). This greatly
-/* improves the performance of the SMTP \fBETRN\fR request, and of the
-/* \fBsendmail -qR\fR command. For domains not in the list, Postfix simply
-/* attempts to deliver all queued mail.
+/* domains that this system is willing to relay mail to). This list
+/* specifies the domains that Postfix accepts in the SMTP \fBETRN\fR
+/* request and in the \fBsendmail -qR\fR command.
/* .IP \fBfork_attempts\fR
/* Number of attempts to \fBfork\fR() a process before giving up.
/* .IP \fBfork_delay\fR
/* SEE ALSO
/* pickup(8) mail pickup daemon
/* postalias(1) maintain alias database
-/* postdrop(1) privileged posting agent
+/* postdrop(1) mail posting utility
/* postfix(1) mail system control
-/* postkick(1) kick a Postfix daemon
+/* postqueue(1) mail queue control
/* qmgr(8) queue manager
-/* showq(8) list mail queue
/* smtpd(8) SMTP server
-/* flushd(8) fast flush service
+/* flush(8) fast flush service
/* syslogd(8) system logging
/* LICENSE
/* .ad
#include <tok822.h>
#include <mail_flush.h>
#include <mail_stream.h>
-#include <smtp_stream.h>
#include <verp_sender.h>
/* Application-specific. */
* Queue file name. Global, so that the cleanup routine can find it when
* called by the run-time error handler.
*/
-static char *sendmail_path;
static void sendmail_cleanup(void);
static NORETURN PRINTFLIKE(2, 3) fatal_error(int, const char *,...);
char *postdrop_command;
uid_t uid = getuid();
int status;
- struct stat st;
int naddr;
/*
}
/*
- * Open the queue file. Save the queue file name, so the run-time error
- * handler can clean up in case of errors.
- *
- * If the queue is not world-writable, let the postdrop command open the
- * queue file.
+ * Let the postdrop command open the queue file for us, and sanity check
+ * the content. XXX Make postdrop a manifest constant.
*/
- if (stat(MAIL_QUEUE_MAILDROP, &st) < 0)
- fatal_error(EX_UNAVAILABLE, "No maildrop directory %s: %m",
- MAIL_QUEUE_MAILDROP);
- if (st.st_mode & S_IWOTH) {
- handle = mail_stream_file(MAIL_QUEUE_MAILDROP,
- MAIL_CLASS_PUBLIC, MAIL_SERVICE_PICKUP);
- sendmail_path = mystrdup(VSTREAM_PATH(handle->stream));
- } else {
- errno = 0;
- postdrop_command = concatenate(var_command_dir, "/postdrop",
+ errno = 0;
+ postdrop_command = concatenate(var_command_dir, "/postdrop",
msg_verbose ? " -v" : (char *) 0, (char *) 0);
- if ((handle = mail_stream_command(postdrop_command)) == 0)
- fatal_error(EX_UNAVAILABLE, "%s(%ld): unable to execute %s: %m",
- saved_sender, (long) uid, postdrop_command);
- myfree(postdrop_command);
- }
+ if ((handle = mail_stream_command(postdrop_command)) == 0)
+ fatal_error(EX_UNAVAILABLE, "%s(%ld): unable to execute %s: %m",
+ saved_sender, (long) uid, postdrop_command);
+ myfree(postdrop_command);
dst = handle->stream;
/*
(status & CLEANUP_STAT_WRITE) ? EX_TEMPFAIL :
EX_UNAVAILABLE, "%s(%ld): %s", saved_sender,
(long) uid, cleanup_strerror(status));
- if (sendmail_path) {
- myfree(sendmail_path);
- sendmail_path = 0;
- }
/*
* Cleanup. Not really necessary as we're about to exit, but good for
myfree(saved_sender);
}
-/* show_queue - show queue status */
-
-static void show_queue(void)
-{
- char buf[VSTREAM_BUFSIZE];
- VSTREAM *showq;
- int n;
-
- /*
- * Connect to the show queue service. Terminate silently when piping into
- * a program that terminates early.
- */
- signal(SIGPIPE, SIG_DFL);
- if ((showq = mail_connect(MAIL_CLASS_PUBLIC, MAIL_SERVICE_SHOWQ, BLOCKING)) != 0) {
- while ((n = vstream_fread(showq, buf, sizeof(buf))) > 0)
- if (vstream_fwrite(VSTREAM_OUT, buf, n) != n
- || vstream_fflush(VSTREAM_OUT) != 0)
- msg_fatal("write error: %m");
-
- if (vstream_fclose(showq))
- msg_warn("close: %m");
- }
-
- /*
- * When the mail system is down, the superuser can still access the queue
- * directly. Just run the showq program in stand-alone mode.
- */
- else if (geteuid() == 0) {
- ARGV *argv;
- int stat;
-
- msg_warn("Mail system is down -- accessing queue directly");
- argv = argv_alloc(6);
- argv_add(argv, MAIL_SERVICE_SHOWQ, "-c", "-u", "-S", (char *) 0);
- for (n = 0; n < msg_verbose; n++)
- argv_add(argv, "-v", (char *) 0);
- argv_terminate(argv);
- stat = mail_run_foreground(var_daemon_dir, argv->argv);
- argv_free(argv);
- }
-
- /*
- * When the mail system is down, unprivileged users are stuck, because by
- * design the mail system contains no set_uid programs. The only way for
- * an unprivileged user to cross protection boundaries is to talk to the
- * showq daemon.
- */
- else {
- msg_fatal("Queue report unavailable - mail system is down");
- }
-}
-
-/* flush_queue - force delivery */
-
-static void flush_queue(void)
-{
-
- /*
- * Trigger the flush queue service.
- */
- if (mail_flush_deferred() < 0)
- msg_warn("Cannot flush mail queue - mail system is down");
-}
-
-/* chat - send command and examine reply */
-
-static void chat(VSTREAM *fp, VSTRING *buf, const char *fmt,...)
-{
- va_list ap;
-
- smtp_get(buf, fp, var_line_limit);
- if (STR(buf)[0] != '2')
- msg_fatal("server rejected ETRN request: %s", STR(buf));
-
- if (msg_verbose)
- msg_info("<<< %s", STR(buf));
-
- if (msg_verbose) {
- va_start(ap, fmt);
- vstring_vsprintf(buf, fmt, ap);
- va_end(ap);
- msg_info(">>> %s", STR(buf));
- }
- va_start(ap, fmt);
- smtp_vprintf(fp, fmt, ap);
- va_end(ap);
-}
-
-/* flush_site - flush mail for site */
-
-static void flush_site(const char *site)
-{
- VSTRING *buf = vstring_alloc(10);
- VSTREAM *fp;
- int sock;
- int status;
-
- /*
- * Make connection to the local SMTP server. Translate "connection
- * refused" into something less misleading.
- */
- vstring_sprintf(buf, "%s:smtp", var_myhostname);
- if ((sock = inet_connect(STR(buf), BLOCKING, 10)) < 0) {
- if (errno == ECONNREFUSED)
- msg_fatal("mail service at %s is down", var_myhostname);
- msg_fatal("connect to mail service at %s: %m", var_myhostname);
- }
- fp = vstream_fdopen(sock, O_RDWR);
-
- /*
- * Prepare for trouble.
- */
- vstream_control(fp, VSTREAM_CTL_EXCEPT, VSTREAM_CTL_END);
- status = vstream_setjmp(fp);
- if (status != 0) {
- switch (status) {
- case SMTP_ERR_EOF:
- msg_fatal("server at %s aborted connection", var_myhostname);
- case SMTP_ERR_TIME:
- msg_fatal("timeout while talking to server at %s", var_myhostname);
- }
- }
- smtp_timeout_setup(fp, 60);
-
- /*
- * Chat with the SMTP server.
- */
- chat(fp, buf, "helo %s", var_myhostname);
- chat(fp, buf, "etrn %s", site);
- chat(fp, buf, "quit");
-
- vstream_fclose(fp);
- vstring_free(buf);
-}
-
static int fatal_status;
/* sendmail_cleanup - callback for the runtime error handler */
* doing complicated things such as memory of buffer management, but if
* for some reason we can't cleanup it is even worse to just die quietly.
*/
- if (sendmail_path) {
- if (remove(sendmail_path))
- msg_warn("sendmail_cleanup: remove %s: %m", sendmail_path);
- else if (msg_verbose)
- msg_info("remove %s", sendmail_path);
- sendmail_path = 0;
- }
exit(fatal_status > 0 ? fatal_status : 1);
}
-/* sendmail_sig - catch signal and clean up */
-
-static void sendmail_sig(int sig)
-{
- fatal_status = sig;
- sendmail_cleanup();
-}
-
/* fatal_error - give up and notify parent */
static void fatal_error(int status, const char *fmt,...)
set_file_limit((off_t) var_message_limit);
signal(SIGPIPE, SIG_IGN);
- signal(SIGXFSZ, SIG_IGN);
-
- signal(SIGHUP, sendmail_sig);
- signal(SIGINT, sendmail_sig);
- signal(SIGQUIT, sendmail_sig);
- signal(SIGTERM, sendmail_sig);
msg_cleanup(sendmail_cleanup);
/*
msg_fatal("cannot handle command-line recipients with -t");
/*
- * Start processing. Some modes are implemented internally (enqueue
- * message), or as network clients (show queue, flush queue); everything
- * else is delegated to external commands.
+ * Start processing. Everything is delegated to external commands.
*/
switch (mode) {
default:
msg_panic("unknown operation mode: %d", mode);
/* NOTREACHED */
case SM_MODE_ENQUEUE:
- if (site_to_flush)
- flush_site(site_to_flush);
- else
+ if (site_to_flush == 0) {
enqueue(flags, sender, full_name, argv + OPTIND);
- exit(0);
+ exit(0);
+ }
+ if (argv[OPTIND])
+ msg_fatal("flush site requires no recipient");
+ ext_argv = argv_alloc(2);
+ argv_add(ext_argv, "postqueue", "-s", site_to_flush, (char *) 0);
+ for (n = 0; n < msg_verbose; n++)
+ argv_add(ext_argv, "-v", (char *) 0);
+ argv_terminate(ext_argv);
+ mail_run_replace(var_command_dir, ext_argv->argv);
+ /* NOTREACHED */
break;
case SM_MODE_MAILQ:
- show_queue();
- exit(0);
- break;
+ if (argv[OPTIND])
+ msg_fatal("display queue mode requires no recipient");
+ ext_argv = argv_alloc(2);
+ argv_add(ext_argv, "postqueue", "-p", (char *) 0);
+ for (n = 0; n < msg_verbose; n++)
+ argv_add(ext_argv, "-v", (char *) 0);
+ argv_terminate(ext_argv);
+ mail_run_replace(var_command_dir, ext_argv->argv);
+ /* NOTREACHED */
case SM_MODE_FLUSHQ:
- flush_queue();
- exit(0);
- break;
+ if (argv[OPTIND])
+ msg_fatal("flush queue mode requires no recipient");
+ ext_argv = argv_alloc(2);
+ argv_add(ext_argv, "postqueue", "-f", (char *) 0);
+ for (n = 0; n < msg_verbose; n++)
+ argv_add(ext_argv, "-v", (char *) 0);
+ argv_terminate(ext_argv);
+ mail_run_replace(var_command_dir, ext_argv->argv);
+ /* NOTREACHED */
case SM_MODE_DAEMON:
if (argv[OPTIND])
msg_fatal("daemon mode requires no recipient");
for (n = 0; n < msg_verbose; n++)
argv_add(ext_argv, "-v", (char *) 0);
argv_split_append(ext_argv, var_alias_db_map, ", \t\r\n");
+ argv_terminate(ext_argv);
mail_run_replace(var_command_dir, ext_argv->argv);
/* NOTREACHED */
case SM_MODE_USER:
BOUNCE_LOG *logfile;
HTABLE *dup_filter = 0;
char status = (strcmp(queue, MAIL_QUEUE_ACTIVE) == 0 ? '*' : ' ');
+ long offset;
while (!vstream_ferror(client) && (rec_type = rec_get(qfile, buf, 0)) > 0) {
start = vstring_str(buf);
arrival_time = atol(start);
break;
case REC_TYPE_SIZE:
- msg_size = atol(start);
+ if ((msg_size = atol(start)) <= 0)
+ msg_size = size;
break;
case REC_TYPE_FROM:
if (*start == 0)
"", "", "", printable(start, '?'));
break;
case REC_TYPE_MESG:
- if (vstream_fseek(qfile, atol(start), SEEK_SET) < 0)
+ if ((offset = atol(start)) > 0
+ && vstream_fseek(qfile, offset, SEEK_SET) < 0)
msg_fatal("seek file %s: %m", VSTREAM_PATH(qfile));
break;
case REC_TYPE_END:
/* Minimal amount of free space in bytes in the queue file system
/* for the SMTP server to accept any mail at all.
/* .IP \fBsmtpd_history_flush_threshold\fR
-/* Flush the command history to postmaster after receipt of RSET etc.
+/* Flush the command history to postmaster after receipt of RSET etc.
/* only if the number of history lines exceeds the given threshold.
/* .SH Tarpitting
/* .ad
char *var_smtpd_null_key;
int var_smtpd_hist_thrsh;
- /*
- * Global state, for stand-alone mode queue file cleanup. When this is
- * non-null at cleanup time, the named file is removed.
- */
-char *smtpd_path;
-
/*
* Silly little macros.
*/
* service.
*/
if (SMTPD_STAND_ALONE(state) == 0) {
- state->dest = mail_stream_service(MAIL_CLASS_PRIVATE,
+ state->dest = mail_stream_service(MAIL_CLASS_PUBLIC,
MAIL_SERVICE_CLEANUP);
if (state->dest == 0
|| attr_print(state->dest->stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER,
ATTR_TYPE_END) != 0)
msg_fatal("unable to connect to the %s %s service",
- MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
- }
-
- /*
- * Otherwise, if the maildrop is writable, create a maildrop file.
- * Arrange for pickup service notification. Make a copy of the pathname
- * so that the file can be deleted in case of a fatal run-time error.
- */
- else if (access(MAIL_QUEUE_MAILDROP, W_OK) == 0) {
- state->dest = mail_stream_file(MAIL_QUEUE_MAILDROP,
- MAIL_CLASS_PUBLIC, MAIL_SERVICE_PICKUP);
- smtpd_path = mystrdup(VSTREAM_PATH(state->dest->stream));
+ MAIL_CLASS_PUBLIC, MAIL_SERVICE_CLEANUP);
}
/*
myfree(state->queue_id);
state->queue_id = 0;
}
- if (smtpd_path) {
- if (remove(smtpd_path))
- msg_warn("remove %s: %m", smtpd_path);
- else if (msg_verbose)
- msg_info("remove %s", smtpd_path);
- myfree(smtpd_path);
- smtpd_path = 0;
- }
if (state->sender) {
myfree(state->sender);
state->sender = 0;
state->dest = 0;
state->cleanup = 0;
- /*
- * Delete the queue file or disable delete on fatal error or interrupt.
- */
- if (smtpd_path) {
- if (state->err != 0) {
- if (remove(smtpd_path))
- msg_warn("remove %s: %m", smtpd_path);
- else if (msg_verbose)
- msg_info("remove %s", smtpd_path);
- }
- myfree(smtpd_path);
- smtpd_path = 0;
- }
-
/*
* Handle any errors. One message may suffer from multiple errors, so
* complain only about the most severe error. Forgive any previous client
debug_peer_restore();
}
-/* smtpd_cleanup - stand-alone mode queue file cleanup */
-
-static void smtpd_cleanup(void)
-{
- char *myname = "smtpd_cleanup";
-
- /*
- * This routine is called by the run-time error handler, right before
- * program exit.
- */
- if (smtpd_path) {
- if (remove(smtpd_path))
- msg_warn("%s: remove %s: %m", myname, smtpd_path);
- else if (msg_verbose)
- msg_info("%s: remove %s", myname, smtpd_path);
- smtpd_path = 0;
- }
-}
-
-/* smtpd_sig - signal handler */
-
-static void smtpd_sig(int sig)
-{
- smtpd_cleanup();
- exit(sig);
-}
-
/* pre_accept - see if tables have changed */
static void pre_accept(char *unused_name, char **unused_argv)
}
}
-/* post_jail_init - post-jail initialization */
-
-static void post_jail_init(char *unused_name, char **unused_argv)
-{
-
- /*
- * Set up signal handlers so that we clean up in stand-alone mode.
- */
- signal(SIGHUP, smtpd_sig);
- signal(SIGINT, smtpd_sig);
- signal(SIGQUIT, smtpd_sig);
- signal(SIGTERM, smtpd_sig);
-}
-
/* pre_jail_init - pre-jail initialization */
static void pre_jail_init(char *unused_name, char **unused_argv)
smtpd_noop_cmds = string_list_init(MATCH_FLAG_NONE, var_smtpd_noop_cmds);
smtpd_check_init();
debug_peer_init();
- msg_cleanup(smtpd_cleanup);
if (var_smtpd_sasl_enable)
#ifdef USE_SASL_AUTH
MAIL_SERVER_BOOL_TABLE, bool_table,
MAIL_SERVER_TIME_TABLE, time_table,
MAIL_SERVER_PRE_INIT, pre_jail_init,
- MAIL_SERVER_POST_INIT, post_jail_init,
MAIL_SERVER_PRE_ACCEPT, pre_accept,
0);
}
if (LEN(buf) > 0 && ISSPACE(*STR(buf))) {
msg_warn("%s: logical line must not start with whitespace: \"%.30s%s\"",
VSTREAM_PATH(fp), STR(buf),
- LEN(buf) > 100 ? "..." : "");
+ LEN(buf) > 30 ? "..." : "");
return (readlline(buf, fp, lineno));
}