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