diff --git a/postfix/HISTORY b/postfix/HISTORY index c2254003e..473ea8a83 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -5880,7 +5880,7 @@ Apologies for any names omitted. 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. @@ -5889,6 +5889,19 @@ Apologies for any names omitted. 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 diff --git a/postfix/INSTALL.sh b/postfix/INSTALL.sh index 5db0ac701..9ae62cfd9 100644 --- a/postfix/INSTALL.sh +++ b/postfix/INSTALL.sh @@ -2,11 +2,31 @@ # 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 <&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 <&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 ] +if [ -f $CONFIG_DIRECTORY/main.cf ] then - . $CONFIG_DIRECTORY/install.cf -elif [ ! -t 0 -a -z "$install_root" ] -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 @@ -218,18 +235,18 @@ done # 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 /*) ;; @@ -256,9 +273,9 @@ chown "$mail_owner" $tempdir/junk >/dev/null 2>&1 || { 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 } @@ -272,7 +289,7 @@ QUEUE_DIRECTORY=$install_root$queue_directory 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. @@ -324,16 +341,13 @@ bin/postconf -c $CONFIG_DIRECTORY -e \ "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 @@ -341,20 +355,29 @@ compare_or_replace a+x,go-w conf/postfix-script $CONFIG_DIRECTORY/postfix-script (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 @@ -362,8 +385,8 @@ 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 @@ -373,19 +396,12 @@ do 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 || { diff --git a/postfix/Makefile b/postfix/Makefile index 8d9e069d9..eb9b06aad 100644 --- a/postfix/Makefile +++ b/postfix/Makefile @@ -14,5 +14,8 @@ default: update 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 diff --git a/postfix/Makefile.in b/postfix/Makefile.in index ffe36d4d3..4e2a83178 100644 --- a/postfix/Makefile.in +++ b/postfix/Makefile.in @@ -29,7 +29,7 @@ install: update sh INSTALL.sh upgrade: update - sh INSTALL.sh SYNOPSIS - postdrop [-rv] [-c config_dir] + postdrop [-rv] [-c config_dir] DESCRIPTION The postdrop command creates a file in the maildrop direc- @@ -49,8 +49,8 @@ POSTDROP(1) POSTDROP(1) A non-standard directory is allowed only if the name is listed in the standard main.cf file, in the - alternate_config_directory configuration parameter - value. + alternate_config_directories configuration parame- + ter value. Only the super-user is allowed to specify arbitrary directory names. diff --git a/postfix/html/postqueue.1.html b/postfix/html/postqueue.1.html index 9df608b87..592c5117b 100644 --- a/postfix/html/postqueue.1.html +++ b/postfix/html/postqueue.1.html @@ -66,8 +66,8 @@ POSTQUEUE(1) POSTQUEUE(1) A non-standard directory is allowed only if the name is listed in the standard main.cf file, in the - alternate_config_directory configuration parameter - value. + alternate_config_directories configuration parame- + ter value. Only the super-user is allowed to specify arbitrary directory names. diff --git a/postfix/man/man1/postdrop.1 b/postfix/man/man1/postdrop.1 index 5e456e9d5..122104924 100644 --- a/postfix/man/man1/postdrop.1 +++ b/postfix/man/man1/postdrop.1 @@ -8,7 +8,7 @@ Postfix mail posting utility .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 @@ -53,7 +53,7 @@ of set-group ID privileges, it is not 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. diff --git a/postfix/man/man1/postqueue.1 b/postfix/man/man1/postqueue.1 index b1fa423b6..5ac8d90f6 100644 --- a/postfix/man/man1/postqueue.1 +++ b/postfix/man/man1/postqueue.1 @@ -70,7 +70,7 @@ In order to avoid exploitation of set-group ID privileges, it is not 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. diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index 0200dca37..dce2d4076 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -18,6 +18,8 @@ /* 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; @@ -104,6 +106,7 @@ #include #include #include +#include #include #ifdef STRCASECMP_IN_STRINGS_H @@ -143,6 +146,8 @@ char *var_syslog_name; 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; @@ -199,6 +204,8 @@ char *var_debug_peer_list; 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) @@ -220,8 +227,9 @@ 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); } @@ -250,14 +258,14 @@ static void check_default_privs(void) 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 */ @@ -267,14 +275,49 @@ static void check_mail_owner(void) 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 */ @@ -294,6 +337,7 @@ void mail_params_init() 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, @@ -389,6 +433,23 @@ void mail_params_init() 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 diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 60b6a2d90..959c017c0 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -49,6 +49,11 @@ extern char *var_mail_owner; 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; @@ -169,13 +174,13 @@ extern char *var_queue_dir; #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; @@ -202,7 +207,7 @@ extern time_t var_starttime; #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; @@ -1373,6 +1378,27 @@ extern char *var_par_dom_match; #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 diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 8e4410526..59eba8e3c 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -15,7 +15,7 @@ * 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 diff --git a/postfix/src/lmtp/lmtp.c b/postfix/src/lmtp/lmtp.c index e943fa855..17a5e9c59 100644 --- a/postfix/src/lmtp/lmtp.c +++ b/postfix/src/lmtp/lmtp.c @@ -227,8 +227,6 @@ #include #include #include -#include -#include /* Utility library. */ diff --git a/postfix/src/postconf/install_table.h b/postfix/src/postconf/install_table.h new file mode 100644 index 000000000..21209fa93 --- /dev/null +++ b/postfix/src/postconf/install_table.h @@ -0,0 +1,5 @@ + 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, diff --git a/postfix/src/postconf/install_vars.h b/postfix/src/postconf/install_vars.h new file mode 100644 index 000000000..9321b1473 --- /dev/null +++ b/postfix/src/postconf/install_vars.h @@ -0,0 +1,5 @@ +char *var_sendmail_path; +char *var_mailq_path; +char *var_newalias_path; +char *var_config_dir; +char *var_manpage_path; diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c index 5df775206..ffcc7fbd8 100644 --- a/postfix/src/postconf/postconf.c +++ b/postfix/src/postconf/postconf.c @@ -131,6 +131,7 @@ DICT *text_table; * Manually extracted. */ #include "smtp_vars.h" +#include "install_vars.h" /* * Lookup tables generated by scanning actual C source files. @@ -153,6 +154,7 @@ static CONFIG_INT_TABLE int_table[] = { static CONFIG_STR_TABLE str_table[] = { #include "str_table.h" #include "smtp_table.h" /* XXX */ +#include "install_table.h" 0, }; diff --git a/postfix/src/postdrop/postdrop.c b/postfix/src/postdrop/postdrop.c index 0176bee50..dacd70fde 100644 --- a/postfix/src/postdrop/postdrop.c +++ b/postfix/src/postdrop/postdrop.c @@ -4,7 +4,7 @@ /* 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. @@ -41,7 +41,7 @@ /* 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. @@ -116,10 +116,14 @@ /* * 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. */ /* @@ -206,7 +210,8 @@ int main(int argc, char **argv) /* * 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) { @@ -267,6 +272,8 @@ int main(int argc, char **argv) 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 diff --git a/postfix/src/postqueue/postqueue.c b/postfix/src/postqueue/postqueue.c index 69cae635c..f2a8b52ce 100644 --- a/postfix/src/postqueue/postqueue.c +++ b/postfix/src/postqueue/postqueue.c @@ -58,7 +58,7 @@ /* 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. @@ -132,6 +132,19 @@ /* 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. */ @@ -177,7 +190,7 @@ static void show_queue(void) 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); @@ -283,7 +296,8 @@ int main(int argc, char **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) { @@ -306,25 +320,7 @@ int main(int argc, char **argv) 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++; @@ -351,6 +347,29 @@ int main(int argc, char **argv) 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. */ diff --git a/postfix/src/util/sys_defs.h b/postfix/src/util/sys_defs.h index e49013be9..5a6cd3296 100644 --- a/postfix/src/util/sys_defs.h +++ b/postfix/src/util/sys_defs.h @@ -52,6 +52,11 @@ #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) @@ -94,6 +99,11 @@ #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 /* @@ -142,6 +152,9 @@ extern int h_errno; #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 /* @@ -208,6 +221,11 @@ extern int opterr; #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 /* @@ -242,6 +260,11 @@ extern int opterr; #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 /* @@ -330,6 +353,11 @@ extern int opterr; #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 @@ -364,6 +392,11 @@ extern int seteuid(uid_t); 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 @@ -397,6 +430,7 @@ extern time_t time(time_t *); extern int seteuid(uid_t); extern int setegid(gid_t); extern int initgroups(const char *, int); +#define DEF_SENDMAIL_PATH "/usr/lib/sendmail" #endif @@ -460,6 +494,11 @@ extern int initgroups(const char *, int); #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 /* @@ -493,6 +532,11 @@ extern int h_errno; /* imports too much stuff */ #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 @@ -523,6 +567,11 @@ extern int h_errno; /* imports too much stuff */ #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 @@ -555,6 +604,10 @@ extern int h_errno; #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 /*