You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by bi...@apache.org on 2018/02/21 23:46:08 UTC
svn commit: r1825018 - in /spamassassin:
branches/3.4/lib/Mail/SpamAssassin/Util.pm branches/3.4/spamd/spamd.raw
trunk/lib/Mail/SpamAssassin/Util.pm trunk/spamd/spamd.raw
Author: billcole
Date: Wed Feb 21 23:46:08 2018
New Revision: 1825018
URL: http://svn.apache.org/viewvc?rev=1825018&view=rev
Log:
Group switching code for bugs #7554 and #7555
Modified:
spamassassin/branches/3.4/lib/Mail/SpamAssassin/Util.pm
spamassassin/branches/3.4/spamd/spamd.raw
spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm
spamassassin/trunk/spamd/spamd.raw
Modified: spamassassin/branches/3.4/lib/Mail/SpamAssassin/Util.pm
URL: http://svn.apache.org/viewvc/spamassassin/branches/3.4/lib/Mail/SpamAssassin/Util.pm?rev=1825018&r1=1825017&r2=1825018&view=diff
==============================================================================
--- spamassassin/branches/3.4/lib/Mail/SpamAssassin/Util.pm (original)
+++ spamassassin/branches/3.4/lib/Mail/SpamAssassin/Util.pm Wed Feb 21 23:46:08 2018
@@ -56,7 +56,7 @@ our @EXPORT = ();
our @EXPORT_OK = qw(&local_tz &base64_decode &untaint_var &untaint_file_path
&exit_status_str &proc_status_ok &am_running_on_windows
&reverse_ip_address &decode_dns_question_entry
- &get_my_locales &parse_rfc822_date
+ &get_my_locales &parse_rfc822_date &get_user_groups
&secure_tmpfile &secure_tmpdir &uri_list_canonicalize);
our $AM_TAINTED;
@@ -1466,13 +1466,43 @@ sub receive_date {
}
###########################################################################
+sub get_user_groups {
+ my $suid = shift;
+ dbg("get_user_groups: uid is $suid\n");
+ my ( $user, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell, $expire ) = getpwuid($suid);
+ my $rgids="$gid ";
+ while ( my($name,$pw,$gid,$members) = getgrent() ) {
+ if ( $members =~ m/\b$user\b/ ) {
+ $rgids .= "$gid ";
+ dbg("get_user_groups: added $gid ($name) to group list which is now: $rgids\n");
+ }
+ }
+ endgrent;
+ chop $rgids;
+ return ($rgids);
+}
+
+
sub setuid_to_euid {
return if (RUNNING_ON_WINDOWS);
# remember the target uid, the first number is the important one
my $touid = $>;
-
+ my $gids = get_user_groups($touid);
+ my ( $pgid, $supgs ) = split (' ',$gids,2);
+ defined $supgs or $supgs=$pgid;
+ if ($( != $pgid) {
+ # Gotta be root for any of this to work
+ $> = 0 ;
+ dbg("util: changing real primary gid from $( to $pgid and supplemental groups to $supgs to match effective uid $touid");
+ POSIX::setgid($pgid);
+ dbg("util: POSIX::setgid($pgid) set errno to $!");
+ $! = 0;
+ $( = $pgid;
+ $) = "$pgid $supgs";
+ dbg("util: assignment \$) = $pgid $supgs set errno to $!");
+ }
if ($< != $touid) {
dbg("util: changing real uid from $< to match effective uid $touid");
# bug 3586: kludges needed to work around platform dependent behavior assigning to $<
@@ -1547,7 +1577,7 @@ sub helper_app_pipe_open_unix {
eval {
# go setuid...
setuid_to_euid();
- dbg("util: setuid: ruid=$< euid=$>");
+ info("util: setuid: ruid=$< euid=$> rgid=$( egid=$) ");
# now set up the fds. due to some wierdness, we may have to ensure that
# we *really* close the correct fd number, since some other code may have
Modified: spamassassin/branches/3.4/spamd/spamd.raw
URL: http://svn.apache.org/viewvc/spamassassin/branches/3.4/spamd/spamd.raw?rev=1825018&r1=1825017&r2=1825018&view=diff
==============================================================================
--- spamassassin/branches/3.4/spamd/spamd.raw (original)
+++ spamassassin/branches/3.4/spamd/spamd.raw Wed Feb 21 23:46:08 2018
@@ -246,7 +246,8 @@ use Mail::SpamAssassin::SubProcBackChann
use Mail::SpamAssassin::SpamdForkScaling qw(:pfstates);
use Mail::SpamAssassin::Logger qw(:DEFAULT log_message);
use Mail::SpamAssassin::Util qw(untaint_var untaint_file_path secure_tmpdir
- exit_status_str am_running_on_windows);
+ exit_status_str am_running_on_windows
+ get_user_groups);
use Mail::SpamAssassin::Timeout;
use Getopt::Long;
@@ -1368,9 +1369,19 @@ sub spawn {
# bug 5518: assignments to $) and $( don't always work on all platforms
# bug 3900: assignments to $> and $< problems with BSD perl bug
# use the POSIX functions to hide the platform specific workarounds
+ dbg("spamd: Privilege de-escalation from user $< and groups $(\n");
+ $! = 0;
POSIX::setgid($ugid); # set effective and real gid
+ dbg("spamd: setgid ERRNO is $!\n");
+ $( = $ugid;
+ $) = "$ugid ".(get_user_groups($uuid)); # set effective and real gid/grouplist another way because we lack initgroups in Perl
+ dbg("spamd: group assignment ERRNO is $!\n");
POSIX::setuid($uuid); # set effective and real UID
+ dbg("spamd: setuid ERRNO is $!\n");
$< = $uuid; $> = $uuid; # bug 5574
+ dbg("spamd: uid assignment ERRNO is $!\n");
+ dbg("spamd: real user is $< \neff user is $> \nreal groups are $( \neff groups are $) \n");
+
# keep the sanity check to catch problems like bug 3900 just in case
if ( $> != $uuid and $> != ( $uuid - 2**32 ) ) {
@@ -1730,7 +1741,7 @@ sub handle_setuid_to_user {
my ($name, $pwd, $uid, $gid, $quota, $comment, $gcos, $dir, $etc) =
getpwnam('nobody');
- $) = "$gid $gid"; # eGID
+ $) = (get_user_groups($uid)); # eGID
$> = $uid; # eUID
if (!defined($uid) || ($> != $uid and $> != ($uid - 2**32))) {
die("spamd: setuid to nobody failed");
@@ -2493,7 +2504,7 @@ sub handle_user_setuid_basic {
}
if ($setuid_to_user) {
- $) = "$gid $gid"; # change eGID
+ $) = (get_user_groups($uid)); # change eGID
$> = $uid; # change eUID
if ( !defined($uid) || ( $> != $uid and $> != ( $uid - 2**32 ) ) ) {
# make it fatal to avoid security breaches
@@ -2715,7 +2726,7 @@ sub handle_user_setuid_with_sql {
}
if ($setuid_to_user) {
- $) = "$gid $gid"; # change eGID
+ $) = (get_user_groups($uid)); # change eGID
$> = $uid; # change eUID
if (!defined($uid) || ($> != $uid and $> != ($uid - 2**32))) {
# make it fatal to avoid security breaches
@@ -2760,7 +2771,7 @@ sub handle_user_setuid_with_ldap {
}
if ($setuid_to_user) {
- $) = "$gid $gid"; # change eGID
+ $) = (get_user_groups($uid)); # change eGID
$> = $uid; # change eUID
if (!defined($uid) || ($> != $uid and $> != ($uid - 2**32))) {
# make it fatal to avoid security breaches
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm?rev=1825018&r1=1825017&r2=1825018&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm Wed Feb 21 23:46:08 2018
@@ -59,7 +59,7 @@ our @EXPORT_OK = qw(&local_tz &base64_de
&reverse_ip_address &decode_dns_question_entry
&secure_tmpfile &secure_tmpdir &uri_list_canonicalize
&get_my_locales &parse_rfc822_date &idn_to_ascii
- &is_valid_utf_8);
+ &is_valid_utf_8 &get_user_groups);
our $AM_TAINTED;
@@ -1586,13 +1586,43 @@ sub receive_date {
}
###########################################################################
+sub get_user_groups {
+ my $suid = shift;
+ dbg("get_user_groups: uid is $suid\n");
+ my ( $user, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell, $expire ) = getpwuid($suid);
+ my $rgids="$gid ";
+ while ( my($name,$pw,$gid,$members) = getgrent() ) {
+ if ( $members =~ m/\b$user\b/ ) {
+ $rgids .= "$gid ";
+ dbg("get_user_groups: added $gid ($name) to group list which is now: $rgids\n");
+ }
+ }
+ endgrent;
+ chop $rgids;
+ return ($rgids);
+}
+
+
sub setuid_to_euid {
return if (RUNNING_ON_WINDOWS);
# remember the target uid, the first number is the important one
my $touid = $>;
-
+ my $gids = get_user_groups($touid);
+ my ( $pgid, $supgs ) = split (' ',$gids,2);
+ defined $supgs or $supgs=$pgid;
+ if ($( != $pgid) {
+ # Gotta be root for any of this to work
+ $> = 0 ;
+ dbg("util: changing real primary gid from $( to $pgid and supplemental groups to $supgs to match effective uid $touid");
+ POSIX::setgid($pgid);
+ dbg("util: POSIX::setgid($pgid) set errno to $!");
+ $! = 0;
+ $( = $pgid;
+ $) = "$pgid $supgs";
+ dbg("util: assignment \$) = $pgid $supgs set errno to $!");
+ }
if ($< != $touid) {
dbg("util: changing real uid from $< to match effective uid $touid");
# bug 3586: kludges needed to work around platform dependent behavior assigning to $<
@@ -1667,7 +1697,7 @@ sub helper_app_pipe_open_unix {
eval {
# go setuid...
setuid_to_euid();
- dbg("util: setuid: ruid=$< euid=$>");
+ info("util: setuid: ruid=$< euid=$> rgid=$( egid=$) ");
# now set up the fds. due to some wierdness, we may have to ensure that
# we *really* close the correct fd number, since some other code may have
Modified: spamassassin/trunk/spamd/spamd.raw
URL: http://svn.apache.org/viewvc/spamassassin/trunk/spamd/spamd.raw?rev=1825018&r1=1825017&r2=1825018&view=diff
==============================================================================
--- spamassassin/trunk/spamd/spamd.raw (original)
+++ spamassassin/trunk/spamd/spamd.raw Wed Feb 21 23:46:08 2018
@@ -246,7 +246,8 @@ use Mail::SpamAssassin::SubProcBackChann
use Mail::SpamAssassin::SpamdForkScaling qw(:pfstates);
use Mail::SpamAssassin::Logger qw(:DEFAULT log_message);
use Mail::SpamAssassin::Util qw(untaint_var untaint_file_path secure_tmpdir
- exit_status_str am_running_on_windows);
+ exit_status_str am_running_on_windows
+ get_user_groups);
use Mail::SpamAssassin::Timeout;
use Getopt::Long;
@@ -1368,9 +1369,19 @@ sub spawn {
# bug 5518: assignments to $) and $( don't always work on all platforms
# bug 3900: assignments to $> and $< problems with BSD perl bug
# use the POSIX functions to hide the platform specific workarounds
+ dbg("spamd: Privilege de-escalation from user $< and groups $(\n");
+ $! = 0;
POSIX::setgid($ugid); # set effective and real gid
+ dbg("spamd: setgid ERRNO is $!\n");
+ $( = $ugid;
+ $) = "$ugid ".(get_user_groups($uuid)); # set effective and real gid/grouplist another way because we lack initgroups in Perl
+ dbg("spamd: group assignment ERRNO is $!\n");
POSIX::setuid($uuid); # set effective and real UID
+ dbg("spamd: setuid ERRNO is $!\n");
$< = $uuid; $> = $uuid; # bug 5574
+ dbg("spamd: uid assignment ERRNO is $!\n");
+ dbg("spamd: real user is $< \neff user is $> \nreal groups are $( \neff groups are $) \n");
+
# keep the sanity check to catch problems like bug 3900 just in case
if ( $> != $uuid and $> != ( $uuid - 2**32 ) ) {
@@ -1730,7 +1741,7 @@ sub handle_setuid_to_user {
my ($name, $pwd, $uid, $gid, $quota, $comment, $gcos, $dir, $etc) =
getpwnam('nobody');
- $) = "$gid $gid"; # eGID
+ $) = (get_user_groups($uid)); # eGID
$> = $uid; # eUID
if (!defined($uid) || ($> != $uid and $> != ($uid - 2**32))) {
die("spamd: setuid to nobody failed");
@@ -2493,7 +2504,7 @@ sub handle_user_setuid_basic {
}
if ($setuid_to_user) {
- $) = "$gid $gid"; # change eGID
+ $) = (get_user_groups($uid)); # change eGID
$> = $uid; # change eUID
if ( !defined($uid) || ( $> != $uid and $> != ( $uid - 2**32 ) ) ) {
# make it fatal to avoid security breaches
@@ -2715,7 +2726,7 @@ sub handle_user_setuid_with_sql {
}
if ($setuid_to_user) {
- $) = "$gid $gid"; # change eGID
+ $) = (get_user_groups($uid)); # change eGID
$> = $uid; # change eUID
if (!defined($uid) || ($> != $uid and $> != ($uid - 2**32))) {
# make it fatal to avoid security breaches
@@ -2760,7 +2771,7 @@ sub handle_user_setuid_with_ldap {
}
if ($setuid_to_user) {
- $) = "$gid $gid"; # change eGID
+ $) = (get_user_groups($uid)); # change eGID
$> = $uid; # change eUID
if (!defined($uid) || ($> != $uid and $> != ($uid - 2**32))) {
# make it fatal to avoid security breaches