20020101
- Security: new alternate_config_directory parameter that
+ Security: new alternate_config_directories parameter that
lists directories that a set-gid command will accept as
its configuration directory. The list must be specified in
the default main.cf file. File: global/mail_conf.c.
connecting to the SMTP port. It is now implemented by
talking to the fast flush service. File: postqueue/postqueue.c.
+20020203
+
+ Cleanup: all installation information is maintained by the
+ main.cf file. The install.cf file is used only when upgrading
+ from an older Postfix release.
+
+ Cleanup: INSTALL.sh now takes non-default settings on the
+ command line, and has a "-upgrade" command line option to
+ turn on non-interactive installation.
+
+ Security: additional run-time checks to discourage sharing
+ of Postfix user/group ID values with other accounts.
+
Open problems:
Low: don't do user@domain and @domain lookups in
# Sample Postfix installation script. Run this from the top-level
# Postfix source directory.
+#
+# Usage: sh INSTALL.sh [-upgrade] name=value ...
PATH=/bin:/usr/bin:/usr/sbin:/usr/etc:/sbin:/etc:/usr/contrib/bin:/usr/gnu/bin:/usr/ucb:/usr/bsd
umask 022
-test -t 0 && cat <<EOF
+# Process command-line settings
+
+for arg
+do
+ case $arg in
+ *=*) IFS= eval $arg;;
+"-upgrade") upgrade=1;;
+ *) echo Error: usage: $0 [-upgrade] name=value ... 1>&2; exit 1;;
+ esac
+done
+
+# Discourage old habits.
+
+test -z "$upgrade" -a ! -t 0 && {
+ echo Error: for non-interactive installation, run: \"$0 -upgrade\" 1>&2
+ exit 1
+}
+
+test -z "$upgrade" && cat <<EOF
Warning: this script replaces existing sendmail or Postfix programs.
Make backups if you want to be able to recover.
only once. All definitions have a reasonable default value.
EOF
-install_root_text="the prefix for installed file names. This is
-useful only if you are building ready-to-install packages for other
-machines."
-
-tempdir_text="directory for scratch files while installing Postfix.
-You must must have write permission in this directory."
-
-config_directory_text="the directory with Postfix configuration
-files. For security reasons this directory must be owned by the
-super-user."
-
-daemon_directory_text="the directory with Postfix daemon programs.
-This directory should not be in the command search path of any
-users."
-
-command_directory_text="the directory with Postfix administrative
-commands. This directory should be in the command search path of
-adminstrative users."
-
-queue_directory_text="the directory with Postfix queues."
-
-sendmail_path_text="the full pathname of the Postfix sendmail
-command. This is the Sendmail-compatible mail posting interface."
-
-newaliases_path_text="the full pathname of the Postfix newaliases
-command. This is the Sendmail-compatible command to build alias
-databases."
-
-mailq_path_text="the full pathname of the Postfix mailq command.
-This is the Sendmail-compatible mail queue listing command."
-
-mail_owner_text="the owner of the Postfix queue. Specify a user
-account with numerical user ID and group ID values that are not
-used by any other user accounts."
-
-setgid_text="the group for mail submission and queue management
-commands. Specify a group name with a numerical group ID that is
-not shared with other accounts, not even with the Postfix account."
-
-manpages_text="where to install the Postfix on-line manual pages."
-
# By now, shells must have functions. Ultrix users must use sh5 or lose.
# The following shell functions replace files/symlinks while minimizing
# the time that a file does not exist, and avoid copying over programs
*) n=; c='\c';;
esac
-# Default settings. Most are clobbered by remembered settings.
+# Prompts.
+
+install_root_prompt="the prefix for installed file names. This is
+useful only if you are building ready-to-install packages for other
+machines."
+
+tempdir_prompt="directory for scratch files while installing Postfix.
+You must must have write permission in this directory."
+
+config_directory_prompt="the directory with Postfix configuration
+files. For security reasons this directory must be owned by the
+super-user."
+
+daemon_directory_prompt="the directory with Postfix daemon programs.
+This directory should not be in the command search path of any
+users."
+
+command_directory_prompt="the directory with Postfix administrative
+commands. This directory should be in the command search path of
+adminstrative users."
+
+queue_directory_prompt="the directory with Postfix queues."
+
+sendmail_path_prompt="the full pathname of the Postfix sendmail
+command. This is the Sendmail-compatible mail posting interface."
+
+newaliases_path_prompt="the full pathname of the Postfix newaliases
+command. This is the Sendmail-compatible command to build alias
+databases."
+
+mailq_path_prompt="the full pathname of the Postfix mailq command.
+This is the Sendmail-compatible mail queue listing command."
+
+mail_owner_prompt="the owner of the Postfix queue. Specify a user
+account with numerical user ID and group ID values that are not
+used by any other user accounts."
+
+setgid_group_prompt="the group for mail submission and for queue
+management commands. Specify a group name with a numerical group
+ID that is not shared with other accounts, not even with the Postfix
+account."
+
+manpage_path_prompt="where to install the Postfix on-line manual
+pages."
+
+# Default settings, just to get started.
: ${install_root=/}
: ${tempdir=`pwd`}
-: ${config_directory=/etc/postfix}
-: ${daemon_directory=/usr/libexec/postfix}
-: ${command_directory=/usr/sbin}
-: ${queue_directory=/var/spool/postfix}
-if [ -f /usr/lib/sendmail ]
- then : ${sendmail_path=/usr/lib/sendmail}
- else : ${sendmail_path=/usr/sbin/sendmail}
-fi
-: ${newaliases_path=/usr/bin/newaliases}
-: ${mailq_path=/usr/bin/mailq}
-: ${mail_owner=postfix}
-: ${setgid=postdrop}
-: ${manpages=/usr/local/man}
+: ${config_directory=`bin/postconf -c conf -h -d config_directory`}
# Find out the location of configuration files.
-test -t 0 &&
-for name in install_root tempdir config_directory
+test -z "$upgrade" && for name in install_root tempdir config_directory
do
while :
do
echo
- eval echo Please specify \$${name}_text | fmt
+ eval echo Please specify \$${name}_prompt | fmt
eval echo \$n "$name: [\$$name]\ \$c"
read ans
case $ans in
"") break;;
- *) eval $name=\$ans; break;;
+ *) case $ans in
+ /*) eval $name=\$ans; break;;
+ *) echo; echo Error: $name should be an absolute path name. 1>&2;;
+ esac;;
esac
done
done
-# Sanity checks
-
-for path in $tempdir $install_root $config_directory
-do
- case $path in
- /*) ;;
- *) echo Error: $path should be an absolute path name. 1>&2; exit 1;;
- esac
-done
-
# In case some systems special-case pathnames beginning with //.
case $install_root in
/) install_root=
esac
-# Load defaults from existing installation.
+# Load defaults from existing installation or from template main.cf file.
CONFIG_DIRECTORY=$install_root$config_directory
-test -f $CONFIG_DIRECTORY/main.cf && {
- for name in daemon_directory command_directory queue_directory mail_owner
- do
- eval $name='"`bin/postconf -c $CONFIG_DIRECTORY -h $name`"' || kill $$
- done
-}
-
-if [ -f $CONFIG_DIRECTORY/install.cf ]
-then
- . $CONFIG_DIRECTORY/install.cf
-elif [ ! -t 0 -a -z "$install_root" ]
+if [ -f $CONFIG_DIRECTORY/main.cf ]
then
- echo Non-interactive install needs the $CONFIG_DIRECTORY/install.cf 1>&2
- echo file from a previous Postfix installation. 1>&2
- echo 1>&2
- echo Use interactive installation instead. 1>&2
- exit 1
+ conf=$CONFIG_DIRECTORY
+else
+ conf=conf
fi
+# Do not destroy parameter settings from environment or command line.
+
+for name in daemon_directory command_directory queue_directory mail_owner \
+ setgid_group sendmail_path newaliases_path mailq_path manpage_path
+do
+ eval : \${$name=\`bin/postconf -c $conf -h $name\`} || kill $$
+done
+
+# Grandfathering: if not in main.cf, get defaults from obsolete install.cf file.
+
+grep setgid_group $CONFIG_DIRECTORY/main.cf 2>&1 >/dev/null || {
+ if [ -f $CONFIG_DIRECTORY/install.cf ]
+ then
+ . $CONFIG_DIRECTORY/install.cf
+ setgid_group=${setgid-$setgid_group}
+ manpage_path=${manpages-$manpage_path}
+ elif [ ! -t 0 -a -z "$install_root" ]
+ then
+ echo \"make upgrade\" requires the $CONFIG_DIRECTORY/main.cf 1>&2
+ echo file from a sufficiently recent Postfix installation. 1>&2
+ echo 1>&2
+ echo Use \"make install\" instead. 1>&2
+ exit 1
+ fi
+}
+
# Override default settings.
-test -t 0 &&
-for name in daemon_directory command_directory \
- queue_directory sendmail_path newaliases_path mailq_path mail_owner\
- setgid manpages
+test -z "$upgrade" && for name in daemon_directory command_directory \
+ queue_directory sendmail_path newaliases_path mailq_path mail_owner \
+ setgid_group manpage_path
do
while :
do
echo
- eval echo Please specify \$${name}_text | fmt
+ eval echo Please specify \$${name}_prompt | fmt
eval echo \$n "$name: [\$$name]\ \$c"
read ans
case $ans in
# Sanity checks
-case $manpages in
- no) echo Error: manpages no longer accepts "no" values. 1>&2
- echo Error: re-run this script in interactive mode. 1>&2; exit 1;;
+case $manpage_path in
+ no) echo Error: manpage_path no longer accepts \"no\" values. 1>&2
+ echo Error: re-run this script with \"make install\". 1>&2; exit 1;;
esac
-case $setgid in
- no) echo Error: setgid no longer accepts "no" values. 1>&2
- echo Error: re-run this script in interactive mode. 1>&2; exit 1;;
+case $setgid_group in
+ no) echo Error: setgid_group no longer accepts \"no\" values. 1>&2
+ echo Error: re-run this script with \"make install\". 1>&2; exit 1;;
esac
for path in $daemon_directory $command_directory \
- $queue_directory $sendmail_path $newaliases_path $mailq_path $manpages
+ $queue_directory $sendmail_path $newaliases_path $mailq_path $manpage_path
do
case $path in
/*) ;;
exit 1
}
-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
+chgrp "$setgid_group" $tempdir/junk >/dev/null 2>&1 || {
+ echo Error: $setgid_group needs an entry in the group file. 1>&2
+ echo Remember, $setgid_group must have a dedicated group id. 1>&2
exit 1
}
SENDMAIL_PATH=$install_root$sendmail_path
NEWALIASES_PATH=$install_root$newaliases_path
MAILQ_PATH=$install_root$mailq_path
-MANPAGES=$install_root$manpages
+MANPAGE_PATH=$install_root$manpage_path
# Create any missing directories.
"command_directory = $command_directory" \
"queue_directory = $queue_directory" \
"mail_owner = $mail_owner" \
+ "setgid_group = $setgid_group" \
+ "sendmail_path = $sendmail_path" \
+ "mailq_path = $mailq_path" \
+ "newaliases_path = $newaliases_path" \
+ "manpage_path = $manpage_path" \
|| exit 1
-(echo "# This file was generated by $0"
-for name in sendmail_path newaliases_path mailq_path setgid manpages
-do
- eval echo $name=\$$name
-done) >$tempdir/junk || exit 1
-compare_or_move a+x,go-w $tempdir/junk $CONFIG_DIRECTORY/install.cf || exit 1
-rm -f $tempdir/junk
-
compare_or_replace a+x,go-w conf/postfix-script $CONFIG_DIRECTORY/postfix-script ||
exit 1
(cd man || exit 1
for dir in man?
- do test -d $MANPAGES/$dir || mkdir -p $MANPAGES/$dir || exit 1
+ do test -d $MANPAGE_PATH/$dir || mkdir -p $MANPAGE_PATH/$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
+ (test -f $MANPAGE_PATH/$file && cmp -s $file $MANPAGE_PATH/$file &&
+ echo Skipping $MANPAGE_PATH/$file...) || {
+ echo Updating $MANPAGE_PATH/$file...
+ rm -f $MANPAGE_PATH/$file
+ cp $file $MANPAGE_PATH/$file || exit 1
+ chmod 644 $MANPAGE_PATH/$file || exit 1
}
done)
-# Use set-gid/group privileges for restricted access.
+# Tighten access of existing directories.
+
+for directory in pid
+do
+ test -d $QUEUE_DIRECTORY/$directory && {
+ chown root $QUEUE_DIRECTORY/$directory || exit 1
+ }
+done
+
+# Apply set-gid/group privileges for restricted access.
for directory in maildrop
do
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
+ # Fix group and permissions if upgrading from world-writable maildrop.
+ chgrp $setgid_group $QUEUE_DIRECTORY/$directory || exit 1
chmod 730 $QUEUE_DIRECTORY/$directory || exit 1
done
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
+ # Fix group and permissions if upgrading from world-accessible directory.
+ chgrp $setgid_group $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
+chgrp $setgid_group $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 || {
update depend printfck clean tidy depend_update: Makefiles
$(MAKE) MAKELEVEL= $@
+install:
+ @echo Please review the 0README instructions first.
+
makefiles Makefiles:
$(MAKE) -f Makefile.in MAKELEVEL= Makefiles
sh INSTALL.sh
upgrade: update
- sh INSTALL.sh </dev/null
+ sh INSTALL.sh -upgrade
depend clean:
set -e; for i in $(DIRS); do \
update depend printfck clean tidy depend_update: Makefiles
$(MAKE) MAKELEVEL= $@
+install:
+ @echo Please review the 0README instructions first.
+
makefiles Makefiles:
$(MAKE) -f Makefile.in MAKELEVEL= Makefiles
One possible use is to add a restriction to main.cf:
- smtpd_recipient_restrictions = ... pcre:/opt/postfix/etc/smtprecipient ...
+ smtpd_recipient_restrictions = ... pcre:/etc/postfix/smtprecipient ...
The regular expressions are read from the file specified - sample
regexp patterns are shown in the Postfix pcre_table(5) manual page.
Incompatible changes with snapshot-200201XX
===========================================
-If you run multiple Postfix instances then you have to specify
-their configuration directories in the default main.cf file as
-"alternate_config_directory = /dir1 /dir2 ...". Otherwise, some
-Postfix sendmail commands will no longer work (namely, the ones
-that are now implemented by set-group ID client programs).
+Postfix will not run if it detects that the postfix user or group
+ID are shared with other accounts on the system. The checks aren't
+exhaustive (that would be too resource consuming) but should be
+sufficient to encourage packagers and developers to do the right
+thing.
This release modifies the existing master.cf file. The local pickup
service is now unprivileged, and the cleanup and flush service are
now "public".
-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 and flush service "private".
+Should you have to back out to a previous release, then you must
+1) edit the master.cf file, make the pickup service "privileged",
+and make the cleanup and flush services "private"; 2) "chmod 755
+/var/spool/postfix/public". To revert to a world-writable mail
+submission directory, "chmod 1733 /var/spool/postfix/maildrop".
+
+If you run multiple Postfix instances on the same machine then you
+now have to specify their configuration directories in the default
+main.cf file as "alternate_config_directories = /dir1 /dir2 ...".
+Otherwise, some Postfix commands will no longer work (namely, the
+ones that are now implemented by set-group ID client programs).
Major changes with snapshot-200201XX
====================================
the queue operations that were implemented by the Postfix sendmail
command.
+Simplification of Postfix installation.
+
+- The install.cf file is gone.
+
+- All installation settings are now kept in the main.cf file, and
+ better default settings are now generated for sendmail_path etc.
+
+- Non-default settings can be specified on the INSTALL.sh command
+ line as name=value arguments.
+
Incompatible changes with snapshot-20011226
===========================================
PATH=/usr/bin:/usr/X11R6/bin
xxgdb $daemon_directory/$process_name $process_id & sleep 5
-# Other configurable parameters.
+# INSTALL-TIME CONFIGURATION INFORMATION
+#
+# The following parameters are used when installing a new Postfix version.
+#
+# sendmail_path: The full pathname of the Postfix sendmail command.
+# This is the Sendmail-compatible mail posting interface.
+#
+# newaliases_path: The full pathname of the Postfix newaliases command.
+# This is the Sendmail-compatible command to build alias databases.
+#
+# mailq_path: The full pathname of the Postfix mailq command. This
+# is the Sendmail-compatible mail queue listing command.
+#
+# setgid_group: The group for mail submission and queue management
+# commands. This must be a group name with a numerical group ID that
+# is not shared with other accounts, not even with the Postfix account.
postdrop - Postfix mail posting utility
<b>SYNOPSIS</b>
- <b>postdrop</b> [<i>-rv</i>] [<b>-c</b> <i>config_dir</i>]
+ <b>postdrop</b> [<b>-rv</b>] [<b>-c</b> <i>config_dir</i>]
<b>DESCRIPTION</b>
The <b>postdrop</b> command creates a file in the <b>maildrop</b> direc-
A non-standard directory is allowed only if the
name is listed in the standard <b>main.cf</b> file, in the
- <b>alternate</b><i>_</i><b>config</b><i>_</i><b>directory</b> configuration parameter
- value.
+ <b>alternate</b><i>_</i><b>config</b><i>_</i><b>directories</b> configuration parame-
+ ter value.
Only the super-user is allowed to specify arbitrary
directory names.
A non-standard directory is allowed only if the
name is listed in the standard <b>main.cf</b> file, in the
- <b>alternate</b><i>_</i><b>config</b><i>_</i><b>directory</b> configuration parameter
- value.
+ <b>alternate</b><i>_</i><b>config</b><i>_</i><b>directories</b> configuration parame-
+ ter value.
Only the super-user is allowed to specify arbitrary
directory names.
.SH SYNOPSIS
.na
.nf
-\fBpostdrop\fR [\fI-rv\fR] [\fB-c \fIconfig_dir\fR]
+\fBpostdrop\fR [\fB-rv\fR] [\fB-c \fIconfig_dir\fR]
.SH DESCRIPTION
.ad
.fi
directory names.
A non-standard directory is allowed only if the name is listed in the
-standard \fBmain.cf\fR file, in the \fBalternate_config_directory\fR
+standard \fBmain.cf\fR file, in the \fBalternate_config_directories\fR
configuration parameter value.
Only the super-user is allowed to specify arbitrary directory names.
possible to specify arbitrary directory names.
A non-standard directory is allowed only if the name is listed in the
-standard \fBmain.cf\fR file, in the \fBalternate_config_directory\fR
+standard \fBmain.cf\fR file, in the \fBalternate_config_directories\fR
configuration parameter value.
Only the super-user is allowed to specify arbitrary directory names.
/* char *var_mail_owner;
/* uid_t var_owner_uid;
/* gid_t var_owner_gid;
+/* char *var_sgid_group;
+/* gid_t var_sgid_gid;
/* char *var_default_privs;
/* uid_t var_default_uid;
/* gid_t var_default_gid;
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
+#include <grp.h>
#include <time.h>
#ifdef STRCASECMP_IN_STRINGS_H
char *var_mail_owner;
uid_t var_owner_uid;
gid_t var_owner_gid;
+char *var_sgid_group;
+gid_t var_sgid_gid;
char *var_default_privs;
uid_t var_default_uid;
gid_t var_default_gid;
int var_debug_peer_level;
int var_fault_inj_code;
+#define MAIN_CONF_FILE "main.cf"
+
/* check_myhostname - lookup hostname and validate */
static const char *check_myhostname(void)
name = get_hostname();
if ((dot = strchr(name, '.')) == 0) {
if ((domain = mail_conf_lookup_eval(VAR_MYDOMAIN)) == 0)
- msg_warn("My hostname %s is not a fully qualified name - set %s or %s in %s/main.cf",
- name, VAR_MYHOSTNAME, VAR_MYDOMAIN, var_config_dir);
+ msg_warn("My hostname %s is not a fully qualified name - set %s or %s in %s/%s",
+ name, VAR_MYHOSTNAME, VAR_MYDOMAIN,
+ var_config_dir, MAIN_CONF_FILE);
else
name = concatenate(name, ".", domain, (char *) 0);
}
struct passwd *pwd;
if ((pwd = getpwnam(var_default_privs)) == 0)
- msg_fatal("unknown %s configuration parameter value: %s",
- VAR_DEFAULT_PRIVS, var_default_privs);
+ msg_fatal("%s:%s: unknown user name value: %s",
+ MAIN_CONF_FILE, VAR_DEFAULT_PRIVS, var_default_privs);
if ((var_default_uid = pwd->pw_uid) == 0)
- msg_fatal("%s: %s: privileged user is not allowed",
- VAR_DEFAULT_PRIVS, var_default_privs);
+ msg_fatal("%s:%s: privileged user is not allowed: %s",
+ MAIN_CONF_FILE, VAR_DEFAULT_PRIVS, var_default_privs);
if ((var_default_gid = pwd->pw_gid) == 0)
- msg_fatal("%s: %s: privileged group is not allowed",
- VAR_DEFAULT_PRIVS, var_default_privs);
+ msg_fatal("%s:%s: privileged group is not allowed: %s",
+ MAIN_CONF_FILE, VAR_DEFAULT_PRIVS, var_default_privs);
}
/* check_mail_owner - lookup owner user attributes and validate */
struct passwd *pwd;
if ((pwd = getpwnam(var_mail_owner)) == 0)
- msg_fatal("unknown %s configuration parameter value: %s",
- VAR_MAIL_OWNER, var_mail_owner);
+ msg_fatal("%s:%s: unknown user name value: %s",
+ MAIN_CONF_FILE, VAR_MAIL_OWNER, var_mail_owner);
if ((var_owner_uid = pwd->pw_uid) == 0)
- msg_fatal("%s: %s: privileged user is not allowed",
- VAR_MAIL_OWNER, var_mail_owner);
+ msg_fatal("%s:%s: privileged user is not allowed: %s",
+ MAIN_CONF_FILE, VAR_MAIL_OWNER, var_mail_owner);
if ((var_owner_gid = pwd->pw_gid) == 0)
- msg_fatal("%s: %s: privileged group is not allowed",
- VAR_DEFAULT_PRIVS, var_mail_owner);
+ msg_fatal("%s:%s: privileged group is not allowed: %s",
+ MAIN_CONF_FILE, VAR_MAIL_OWNER, var_mail_owner);
+
+ /*
+ * This detects only some forms of sharing. Enumerating the entire
+ * password file name space could be expensive. The purpose of this code
+ * is to discourage user ID sharing by developers and package
+ * maintainers.
+ */
+ if ((pwd = getpwuid(var_owner_uid)) != 0
+ && strcmp(pwd->pw_name, var_mail_owner) != 0)
+ msg_fatal("%s:%s: %s is sharing the user ID with %s",
+ MAIN_CONF_FILE, VAR_MAIL_OWNER, var_mail_owner, pwd->pw_name);
+}
+
+/* check_sgid_group - lookup setgid group attributes and validate */
+
+static void check_sgid_group(void)
+{
+ struct group *grp;
+
+ if ((grp = getgrnam(var_sgid_group)) == 0)
+ msg_fatal("%s:%s: unknown group name: %s",
+ MAIN_CONF_FILE, VAR_SGID_GROUP, var_sgid_group);
+ if ((var_sgid_gid = grp->gr_gid) == 0)
+ msg_fatal("%s:%s: privileged group is not allowed: %s",
+ MAIN_CONF_FILE, VAR_SGID_GROUP, var_sgid_group);
+
+ /*
+ * This detects only some forms of sharing. Enumerating the entire group
+ * file name space could be expensive. The purpose of this code is to
+ * discourage group ID sharing by developers and package maintainers.
+ */
+ if ((grp = getgrgid(var_sgid_gid)) != 0
+ && strcmp(grp->gr_name, var_sgid_group) != 0)
+ msg_fatal("%s:%s: group %s is sharing the group ID with %s",
+ MAIN_CONF_FILE, VAR_SGID_GROUP, var_sgid_group, grp->gr_name);
}
/* mail_params_init - configure built-in parameters */
VAR_MAIL_NAME, DEF_MAIL_NAME, &var_mail_name, 1, 0,
VAR_SYSLOG_NAME, DEF_SYSLOG_NAME, &var_syslog_name, 1, 0,
VAR_MAIL_OWNER, DEF_MAIL_OWNER, &var_mail_owner, 1, 0,
+ VAR_SGID_GROUP, DEF_SGID_GROUP, &var_sgid_group, 1, 0,
VAR_MYDEST, DEF_MYDEST, &var_mydest, 0, 0,
VAR_MYORIGIN, DEF_MYORIGIN, &var_myorigin, 1, 0,
VAR_RELAYHOST, DEF_RELAYHOST, &var_relayhost, 0, 0,
get_mail_conf_time_table(time_defaults);
check_default_privs();
check_mail_owner();
+ check_sgid_group();
+
+ /*
+ * Discourage UID or GID sharing.
+ */
+ if (var_default_uid == var_owner_uid)
+ msg_fatal("%s: %s and %s must not have the same user ID",
+ MAIN_CONF_FILE, VAR_DEFAULT_PRIVS, VAR_MAIL_OWNER);
+ if (var_default_gid == var_owner_gid)
+ msg_fatal("%s: %s and %s must not have the same group ID",
+ MAIN_CONF_FILE, VAR_DEFAULT_PRIVS, VAR_MAIL_OWNER);
+ if (var_default_gid == var_sgid_gid)
+ msg_fatal("%s: %s and %s must not have the same group ID",
+ MAIN_CONF_FILE, VAR_DEFAULT_PRIVS, VAR_SGID_GROUP);
+ if (var_owner_gid == var_sgid_gid)
+ msg_fatal("%s: %s and %s must not have the same group ID",
+ MAIN_CONF_FILE, VAR_MAIL_OWNER, VAR_SGID_GROUP);
/*
* Variables whose defaults are determined at runtime, after other
extern uid_t var_owner_uid;
extern gid_t var_owner_gid;
+#define VAR_SGID_GROUP "setgid_group"
+#define DEF_SGID_GROUP "postdrop"
+extern char *var_sgid_group;
+extern gid_t var_sgid_gid;
+
#define VAR_DEFAULT_PRIVS "default_privs"
#define DEF_DEFAULT_PRIVS "nobody"
extern char *var_default_privs;
#define VAR_DAEMON_DIR "daemon_directory"
#ifndef DEF_DAEMON_DIR
-#define DEF_DAEMON_DIR "$program_directory"
+#define DEF_DAEMON_DIR "/usr/libexec/postfix"
#endif
extern char *var_daemon_dir;
#define VAR_COMMAND_DIR "command_directory"
#ifndef DEF_COMMAND_DIR
-#define DEF_COMMAND_DIR "$program_directory"
+#define DEF_COMMAND_DIR "/usr/sbin"
#endif
extern char *var_command_dir;
#endif
extern char *var_config_dir;
-#define VAR_CONFIG_DIRS "alternate_config_directory"
+#define VAR_CONFIG_DIRS "alternate_config_directories"
#define DEF_CONFIG_DIRS ""
extern char *var_config_dirs;
#define DEF_FAULT_INJ_CODE 0
extern int var_fault_inj_code;
+ /*
+ * Install/upgrade information.
+ */
+#define VAR_SENDMAIL_PATH "sendmail_path"
+#ifndef DEF_SENDMAIL_PATH
+#define DEF_SENDMAIL_PATH "/usr/sbin/sendmail"
+#endif
+
+#define VAR_MAILQ_PATH "mailq_path"
+#ifndef DEF_MAILQ_PATH
+#define DEF_MAILQ_PATH "/usr/bin/mailq"
+#endif
+
+#define VAR_NEWALIAS_PATH "newaliases_path"
+#ifndef DEF_NEWALIAS_PATH
+#define DEF_NEWALIAS_PATH "/usr/bin/newaliases"
+#endif
+
+#define VAR_MANPAGE_PATH "manpage_path"
+#define DEF_MANPAGE_PATH "/usr/local/man"
+
/* LICENSE
/* .ad
/* .fi
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "Snapshot-20020101"
+#define DEF_MAIL_VERSION "Snapshot-20020103"
extern char *var_mail_version;
/* LICENSE
#include <string.h>
#include <fcntl.h>
#include <dict.h>
-#include <pwd.h>
-#include <grp.h>
/* Utility library. */
--- /dev/null
+ VAR_SENDMAIL_PATH, DEF_SENDMAIL_PATH, &var_sendmail_path, 1, 0,
+ VAR_MAILQ_PATH, DEF_MAILQ_PATH, &var_mailq_path, 1, 0,
+ VAR_NEWALIAS_PATH, DEF_NEWALIAS_PATH, &var_newalias_path, 1, 0,
+ VAR_CONFIG_DIR, DEF_CONFIG_DIR, &var_config_dir, 1, 0,
+ VAR_MANPAGE_PATH, DEF_MANPAGE_PATH, &var_manpage_path, 1, 0,
--- /dev/null
+char *var_sendmail_path;
+char *var_mailq_path;
+char *var_newalias_path;
+char *var_config_dir;
+char *var_manpage_path;
* Manually extracted.
*/
#include "smtp_vars.h"
+#include "install_vars.h"
/*
* Lookup tables generated by scanning actual C source files.
static CONFIG_STR_TABLE str_table[] = {
#include "str_table.h"
#include "smtp_table.h" /* XXX */
+#include "install_table.h"
0,
};
/* SUMMARY
/* Postfix mail posting utility
/* SYNOPSIS
-/* \fBpostdrop\fR [\fI-rv\fR] [\fB-c \fIconfig_dir\fR]
+/* \fBpostdrop\fR [\fB-rv\fR] [\fB-c \fIconfig_dir\fR]
/* DESCRIPTION
/* The \fBpostdrop\fR command creates a file in the \fBmaildrop\fR
/* directory and copies its standard input to the file.
/* directory names.
/*
/* A non-standard directory is allowed only if the name is listed in the
-/* standard \fBmain.cf\fR file, in the \fBalternate_config_directory\fR
+/* standard \fBmain.cf\fR file, in the \fBalternate_config_directories\fR
/* configuration parameter value.
/*
/* Only the super-user is allowed to specify arbitrary directory names.
/*
* WARNING WARNING WARNING
*
- * This software is designed to run set-gid on systems that cannot afford a
- * world-writable spool directory. In order to make this restriction work,
- * this software should not run any external commands, nor should it take
- * any configuration information from the user.
+ * This software is designed to run set-gid. In order to avoid exploitation of
+ * privilege, this software should not run any external commands, nor should
+ * it take any information from the user unless that information can be
+ * properly sanitized. To get an idea of how much information a process can
+ * inherit from a potentially hostile user, examine all the members of the
+ * process structure (typically, in /usr/include/sys/proc.h): the current
+ * directory, open files, timers, signals, environment, command line, umask,
+ * and so on.
*/
/*
/*
* Parse JCL. This program is set-gid and must sanitize all command-line
* arguments. The configuration directory argument is validated by the
- * mail configuration read routine.
+ * mail configuration read routine. Don't do complex things until we have
+ * completed initializations.
*/
while ((c = GETOPT(argc, argv, "c:rv")) > 0) {
switch (c) {
signal(SIGTERM, postdrop_sig);
msg_cleanup(postdrop_cleanup);
+ /* End of initializations. */
+
/*
* Create queue file. mail_stream_file() never fails. Send the queue ID
* to the caller. Stash away a copy of the queue file name so we can
/* possible to specify arbitrary directory names.
/*
/* A non-standard directory is allowed only if the name is listed in the
-/* standard \fBmain.cf\fR file, in the \fBalternate_config_directory\fR
+/* standard \fBmain.cf\fR file, in the \fBalternate_config_directories\fR
/* configuration parameter value.
/*
/* Only the super-user is allowed to specify arbitrary directory names.
/* Application-specific. */
+ /*
+ * WARNING WARNING WARNING
+ *
+ * This software is designed to run set-gid. In order to avoid exploitation of
+ * privilege, this software should not run any external commands, nor should
+ * it take any information from the user, unless that information can be
+ * properly sanitized. To get an idea of how much information a process can
+ * inherit from a potentially hostile user, examine all the members of the
+ * process structure (typically, in /usr/include/sys/proc.h): the current
+ * directory, open files, timers, signals, environment, command line, umask,
+ * and so on.
+ */
+
/*
* Modes of operation.
*/
msg_warn("Mail system is down -- accessing queue directly");
argv = argv_alloc(6);
- argv_add(argv, MAIL_SERVICE_SHOWQ, "-c", "-u", "-S", (char *) 0);
+ argv_add(argv, MAIL_SERVICE_SHOWQ, "-u", "-S", (char *) 0);
for (n = 0; n < msg_verbose; n++)
argv_add(argv, "-v", (char *) 0);
argv_terminate(argv);
/*
* Parse JCL. This program is set-gid and must sanitize all command-line
* parameters. The configuration directory argument is validated by the
- * mail configuration read routine.
+ * mail configuration read routine. Don't do complex things until we have
+ * completed initializations.
*/
while ((c = GETOPT(argc, argv, "c:fps:v")) > 0) {
switch (c) {
if (mode != PQ_MODE_DEFAULT)
usage();
mode = PQ_MODE_FLUSH_SITE;
- if (*optarg == '[' && *(last = optarg + strlen(optarg) - 1) == ']') {
-
- *last = 0;
- if (valid_hostaddr(optarg + 1, DONT_GRIPE))
- site_to_flush = optarg;
- else
- site_to_flush = 0;
- *last = ']';
- } else {
- if (valid_hostname(optarg, DONT_GRIPE)
- || valid_hostaddr(optarg, DONT_GRIPE))
- site_to_flush = optarg;
- else
- site_to_flush = 0;
- }
- if (site_to_flush == 0)
- msg_fatal_status(EX_USAGE,
- "Cannot flush mail queue - invalid destination: \"%.100s%s\"",
- optarg, strlen(optarg) > 100 ? "..." : "");
+ site_to_flush = optarg;
break;
case 'v':
msg_verbose++;
signal(SIGPIPE, SIG_IGN);
+ /* End of initializations. */
+
+ /*
+ * Further input validation.
+ */
+ if (site_to_flush != 0) {
+ if (*site_to_flush == '['
+ && *(last = optarg + strlen(site_to_flush) - 1) == ']') {
+ *last = 0;
+ if (!valid_hostaddr(optarg + 1, DONT_GRIPE))
+ site_to_flush = 0;
+ *last = ']';
+ } else {
+ if (!valid_hostname(optarg, DONT_GRIPE)
+ && !valid_hostaddr(optarg, DONT_GRIPE))
+ site_to_flush = 0;
+ }
+ if (site_to_flush == 0)
+ msg_fatal_status(EX_USAGE,
+ "Cannot flush mail queue - invalid destination: \"%.100s%s\"",
+ optarg, strlen(optarg) > 100 ? "..." : "");
+ }
+
/*
* Start processing.
*/
#define STATFS_IN_SYS_MOUNT_H
#define HAS_POSIX_REGEXP
#define HAS_ST_GEN /* struct stat contains inode generation number */
+#define DEF_SENDMAIL_PATH "/usr/sbin/sendmail"
+#define DEF_MAILQ_PATH "/usr/bin/mailq"
+#define DEF_NEWALIAS_PATH "/usr/bin/newaliases"
+#define DEF_COMMAND_DIR "/usr/sbin"
+#define DEF_DAEMON_DIR "/usr/libexec/postfix"
#endif
#if defined(FREEBSD2) || defined(FREEBSD3) || defined(FREEBSD4)
#define PRINTFLIKE(x,y)
#define SCANFLIKE(x,y)
#define HAS_NETINFO
+#define DEF_SENDMAIL_PATH "/usr/sbin/sendmail"
+#define DEF_MAILQ_PATH "/usr/bin/mailq"
+#define DEF_NEWALIAS_PATH "/usr/bin/newaliases"
+#define DEF_COMMAND_DIR "/usr/sbin"
+#define DEF_DAEMON_DIR "/usr/libexec/postfix"
#endif
/*
#define DUP2_DUPS_CLOSE_ON_EXEC
#define MISSING_USLEEP
#define NO_HERRNO
+#define DEF_SENDMAIL_PATH "/usr/lib/sendmail"
+#define DEF_COMMAND_DIR "/usr/etc"
+#define DEF_DAEMON_DIR "/usr/libexec/postfix"
#endif
/*
#define STATFS_IN_SYS_VFS_H
#define memmove(d,s,l) bcopy(s,d,l)
#define NO_HERRNO
+#define DEF_SENDMAIL_PATH "/usr/lib/sendmail"
+#define DEF_MAILQ_PATH "/usr/ucb/mailq"
+#define DEF_NEWALIAS_PATH "/usr/ucb/newaliases"
+#define DEF_COMMAND_DIR "/usr/etc"
+#define DEF_DAEMON_DIR "/usr/libexec/postfix"
#endif
/*
#define LOCAL_CONNECT stream_connect
#define LOCAL_TRIGGER stream_trigger
#define HAS_VOLATILE_LOCKS
+#define DEF_SENDMAIL_PATH "/usr/lib/sendmail"
+#define DEF_MAILQ_PATH "/usr/bin/mailq"
+#define DEF_NEWALIAS_PATH "/usr/bin/newaliases"
+#define DEF_COMMAND_DIR "/usr/sbin"
+#define DEF_DAEMON_DIR "/usr/libexec/postfix"
#endif
/*
#define USE_STATVFS
#define STATVFS_IN_SYS_STATVFS_H
#define STRCASECMP_IN_STRINGS_H
+#define DEF_SENDMAIL_PATH "/usr/lib/sendmail"
+#define DEF_MAILQ_PATH "/usr/sbin/mailq"
+#define DEF_NEWALIAS_PATH "/usr/sbin/newaliases"
+#define DEF_COMMAND_DIR "/usr/sbin"
+#define DEF_DAEMON_DIR "/usr/libexec/postfix"
#endif
#ifdef AIX4
extern int setegid(gid_t);
extern int initgroups(const char *, int);
#endif
+#define DEF_SENDMAIL_PATH "/usr/lib/sendmail"
+#define DEF_MAILQ_PATH "/usr/sbin/mailq"
+#define DEF_NEWALIAS_PATH "/usr/sbin/newaliases"
+#define DEF_COMMAND_DIR "/usr/sbin"
+#define DEF_DAEMON_DIR "/usr/libexec/postfix"
#endif
extern int seteuid(uid_t);
extern int setegid(gid_t);
extern int initgroups(const char *, int);
+#define DEF_SENDMAIL_PATH "/usr/lib/sendmail"
#endif
#define UNIX_DOMAIN_CONNECT_BLOCKS_FOR_ACCEPT
#define PREPEND_PLUS_TO_OPTSTRING
#define HAS_POSIX_REGEXP
+#define DEF_SENDMAIL_PATH "/usr/sbin/sendmail"
+#define DEF_MAILQ_PATH "/usr/bin/mailq"
+#define DEF_NEWALIAS_PATH "/usr/bin/newaliases"
+#define DEF_COMMAND_DIR "/usr/sbin"
+#define DEF_DAEMON_DIR "/usr/libexec/postfix"
#endif
/*
#define USE_STATFS
#define STATFS_IN_SYS_VFS_H
#define HAS_POSIX_REGEXP
+#define DEF_SENDMAIL_PATH "/usr/sbin/sendmail"
+#define DEF_MAILQ_PATH "/usr/bin/mailq"
+#define DEF_NEWALIAS_PATH "/usr/bin/newaliases"
+#define DEF_COMMAND_DIR "/usr/sbin"
+#define DEF_DAEMON_DIR "/usr/libexec/postfix"
#endif
#ifdef HPUX10
#define USE_STATFS
#define STATFS_IN_SYS_VFS_H
#define HAS_POSIX_REGEXP
+#define DEF_SENDMAIL_PATH "/usr/sbin/sendmail"
+#define DEF_MAILQ_PATH "/usr/bin/mailq"
+#define DEF_NEWALIAS_PATH "/usr/bin/newaliases"
+#define DEF_COMMAND_DIR "/usr/sbin"
+#define DEF_DAEMON_DIR "/usr/libexec/postfix"
#endif
#ifdef HPUX9
#define USE_STATFS
#define STATFS_IN_SYS_VFS_H
#define HAS_POSIX_REGEXP
+#define DEF_SENDMAIL_PATH "/usr/bin/sendmail"
+#define DEF_MAILQ_PATH "/usr/bin/mailq"
+#define DEF_NEWALIAS_PATH "/usr/bin/newaliases"
+#define DEF_DAEMON_DIR "/usr/libexec/postfix"
#endif
/*