diff -ur spamassassin.orig/spamd/spamd.raw spamassassin/spamd/spamd.raw --- spamassassin.orig/spamd/spamd.raw 2005-06-13 03:43:26.000000000 -0700 +++ spamassassin/spamd/spamd.raw 2005-06-27 20:01:12.000000000 -0700 @@ -200,6 +200,7 @@ 'username|u=s' => \$opt{'username'}, 'version|V' => \$opt{'version'}, 'virtual-config-dir=s' => \$opt{'virtual-config-dir'}, + 'virtual-setuid-separator=s' => \$opt{'virtual-setuid-separator'}, 'v' => \$opt{'vpopmail'}, 'vpopmail!' => \$opt{'vpopmail'}, @@ -413,7 +414,7 @@ $opt{'username'} || $> != 0 || $opt{'vpopmail'} || - (!$opt{'user-config'} && !($opt{'setuid-with-sql'}||$opt{'setuid-with-ldap'})) + (!$opt{'user-config'} && !($opt{'setuid-with-sql'}||$opt{'setuid-with-ldap'}||($opt{'virtual-config-dir'}&&$opt{'virtual-setuid-separator'}))) ) ? 0 : 1; # always copy the config, later code may disable @@ -1768,6 +1769,33 @@ sub handle_virtual_config_dir { my ($username) = @_; + if ($opt{'virtual-setuid-separator'} and $username =~ s/^([\x20-\xff]+?)\Q$opt{'virtual-setuid-separator'}\E//) { + my $userid = $1; + my ( $name, $pwd, $uid, $gid, $quota, $comment, $gcos, $dir, $etc ) = + $userid =~ /^\d+$/ ? getpwuid($userid) : getpwnam($userid); + + if ( !$spamtest->{'paranoid'} && !defined($uid) ) { + + #if we are given a username, but can't look it up, + #Maybe NIS is down? lets break out here to allow + #them to get 'defaults' when we are not running paranoid. + logmsg("handle_user: unable to find user '$userid'!"); + return 0; + } + + if ($setuid_to_user) { + $) = "$gid $gid"; # change eGID + $> = $uid; # change eUID + if ( !defined($uid) || ( $> != $uid and $> != ( $uid - 2**32 ) ) ) { + logmsg("fatal: setuid to $uid:$gid failed"); + die; # make it fatal to avoid security breaches + } + else { + logmsg("info: setuid to $uid:$gid succeeded"); + } + } + } + my $dir = $opt{'virtual-config-dir'}; my $userdir; my $prefsfile; @@ -1778,10 +1806,12 @@ my $localpart = ''; my $domain = ''; if ( $safename =~ /^(.*)\@(.*)$/ ) { $localpart = $1; $domain = $2; } + my $homedir = (getpwuid($>))[7]; $dir =~ s/\%u/${safename}/g; $dir =~ s/\%l/${localpart}/g; $dir =~ s/\%d/${domain}/g; + $dir =~ s/\%h/${homedir}/g; $dir =~ s/\%\%/\%/g; $userdir = $dir; @@ -2162,6 +2192,8 @@ enables use of -H) --virtual-config-dir=dir Enable pattern based Virtual configs (needs -x) + --virtual-config-separator=chars Allows setuid operation of virtual configs + by prefixing email with setuid username -r pidfile, --pidfile Write the process id to pidfile -s facility, --syslog=facility Specify the syslog facility --syslog-socket=type How to connect to syslogd @@ -2293,6 +2325,9 @@ words, if the username is an email address, this is the part after the C<@> sign. +=item %h -- replaced with the home directory of the current user. This is +particularly useful when using the B<--virtual-setuid-separator> option). + =item %% -- replaced with a single percent sign (%). =back @@ -2319,6 +2354,15 @@ The pattern B expand to an absolute directory when spamd is running daemonized (B<-d>). +=item B<--virtual-setuid-separator>=I + +Interprets a setuid username from spamc followed by the value followed by the +real virtual username. For example, if set to C<::>, spamc could send a +virtual username of C which would instruct spamd to +setuid() to the C user before continuing. + +This setting has no effect without B<--virtual-config-dir>. + =item B<-r> I, B<--pidfile>=I Write the process ID of the spamd parent to the file specified by I.