You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by jm...@apache.org on 2004/06/19 04:03:14 UTC
svn commit: rev 21433 - in incubator/spamassassin/trunk: lib/Mail/SpamAssassin lib/Mail/SpamAssassin/Conf rules
Author: jm
Date: Fri Jun 18 19:03:13 2004
New Revision: 21433
Modified:
incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm
incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm
incubator/spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm
incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Reporter.pm
incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm
incubator/spamassassin/trunk/rules/20_html_tests.cf
incubator/spamassassin/trunk/rules/20_ratware.cf
Log:
allow_user_rules fixes: block user-defined SenderBase rules; sanitise arguments to many regexp rules; run helper apps as uid=user euid=user; ensure regexps are valid before they are used in the ruleset. fix a couple of rules to work with these changes.
Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm (original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm Fri Jun 18 19:03:13 2004
@@ -3086,6 +3086,7 @@
$self->{rewrite_header} = { };
$self->{user_rules_to_compile} = { };
+ $self->{user_defined_rules} = { };
$self->{headers_spam} = { };
$self->{headers_ham} = { };
Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm (original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm Fri Jun 18 19:03:13 2004
@@ -625,6 +625,16 @@
return;
}
+ # all of these rule types are regexps
+ if ($type == $Mail::SpamAssassin::Conf::TYPE_HEAD_TESTS
+ || $type == $Mail::SpamAssassin::Conf::TYPE_BODY_TESTS
+ || $type == $Mail::SpamAssassin::Conf::TYPE_FULL_TESTS
+ || $type == $Mail::SpamAssassin::Conf::TYPE_RAWBODY_TESTS
+ || $type == $Mail::SpamAssassin::Conf::TYPE_URI_TESTS)
+ {
+ return unless $self->is_regexp_valid($name, $text);
+ }
+
$conf->{tests}->{$name} = $text;
$conf->{test_types}->{$name} = $type;
$conf->{tflags}->{$name} ||= '';
@@ -633,6 +643,7 @@
if ($self->{scoresonly}) {
$conf->{user_rules_to_compile}->{$type} = 1;
+ $conf->{user_defined_rules}->{$name} = 1;
}
}
@@ -646,6 +657,18 @@
else {
# initialize the array, and create one element
$conf->{regression_tests}->{$name} = [ [$ok_or_fail, $string] ];
+ }
+}
+
+sub is_regexp_valid {
+ my ($self, $name, $re) = @_;
+ if (eval { ("" =~ m{$re}); 1; }) {
+ return 1;
+
+ } else {
+ warn "invalid regexp for rule $name: $re\n";
+ $self->{conf}->{errors}++;
+ return 0;
}
}
Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm (original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Dns.pm Fri Jun 18 19:03:13 2004
@@ -207,6 +207,12 @@
}
# senderbase
elsif ($subtest =~ s/^sb://) {
+ # SB rules are not available to users
+ if ($self->{conf}->{user_defined_rules}->{$rule}) {
+ dbg ("RBL: skipping rule '$rule': not supported when user-defined");
+ next;
+ }
+
$rdatastr =~ s/^"?\d+-//;
$rdatastr =~ s/"$//;
my %sb = ($rdatastr =~ m/(?:^|\|)(\d+)=([^|]+)/g);
@@ -224,11 +230,7 @@
my $untainted = $1;
$subtest = $untainted;
- # Mail::SpamAssassin::Util::untaint_var (\%sb);
- # dbg ("$subtest");
- # dbg ("$rdatastr");
-
- $self->got_hit($rule, "SenderBase: ") if !$undef && eval "$subtest";
+ $self->got_hit($rule, "SenderBase: ") if !$undef && eval $subtest;
}
# bitmask
elsif ($subtest =~ /^\d+$/) {
@@ -736,7 +738,12 @@
}
dbg("DCC command: ".join(' ', $path, "-H", $opts, "< '$tmpf'", "2>&1"),'dcc',-1);
- my $pid = open(DCC, join(' ', $path, "-H", $opts, "< '$tmpf'", "2>&1", '|')) || die "$!\n";
+
+ # my $pid = open(DCC, join(' ', $path, "-H", $opts, "< '$tmpf'", "2>&1", '|')) || die "$!\n";
+ my $pid = Mail::SpamAssassin::Util::helper_app_pipe_open(*DCC,
+ $tmpf, 1, $path, "-H", split(' ', $opts));
+ $pid or die "$!\n";
+
my @null = <DCC>;
close DCC;
@@ -869,7 +876,12 @@
$opts =~ s/[^-A-Za-z0-9 \/_]/_/gs; # sanitise
dbg("Pyzor command: ".join(' ', $path, $opts, "check", "< '$tmpf'", "2>&1"),'pyzor',-1);
- my $pid = open(PYZOR, join(' ', $path, $opts, "check", "< '$tmpf'", "2>&1", '|')) || die "$!\n";
+
+ #my $pid = open(PYZOR, join(' ', $path, $opts, "check", "< '$tmpf'", "2>&1", '|')) || die "$!\n";
+ my $pid = Mail::SpamAssassin::Util::helper_app_pipe_open(*PYZOR,
+ $tmpf, 1, $path, split(' ', $opts), "check");
+ $pid or die "$!\n";
+
$response = <PYZOR>;
close PYZOR;
Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm (original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/EvalTests.pm Fri Jun 18 19:03:13 2004
@@ -3113,7 +3113,7 @@
$self->{html}{"inside_$tag"} =~ /^([\<\>\=\!\-\+ 0-9]+)$/;
my $val = $1;
- return eval "$val $expr";
+ return eval "\$val $expr";
}
sub html_image_only {
@@ -3167,7 +3167,8 @@
}
sub html_eval {
- my ($self, undef, $test, $expr) = @_;
+ my ($self, undef, $test, $rawexpr) = @_;
+ $rawexpr =~ /^([\<\>\=\!\-\+ 0-9]+)$/; my $expr = $1;
# workaround bug 3320: wierd perl bug where additional, very explicit
# untainting into a new var is required.
@@ -3175,13 +3176,24 @@
return unless defined($tainted);
$tainted =~ /^(.*)$/; my $val = $1;
- return eval "qq{\Q$val\E} $expr";
+ # just use the value in $val, don't copy it needlessly
+ return eval "\$val $expr";
}
-sub html_text {
- my ($self, undef, $text, $expr) = @_;
+sub html_text_match {
+ my ($self, undef, $text, $regexp) = @_;
for my $string (@{ $self->{html}{$text} }) {
- if (defined $string && eval "qq{\Q$string\E} $expr") {
+ if (defined $string && $string =~ /${regexp}/) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub html_text_not_match {
+ my ($self, undef, $text, $regexp) = @_;
+ for my $string (@{ $self->{html}{$text} }) {
+ if (defined $string && $string !~ /${regexp}/) {
return 1;
}
}
Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Reporter.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Reporter.pm (original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Reporter.pm Fri Jun 18 19:03:13 2004
@@ -286,7 +286,10 @@
$opts = $1;
}
- my $pid = open(DCC, join(' ', $path, "-t many", $opts, "< '$tmpf'", ">/dev/null 2>&1", '|')) || die "$!\n";
+ my $pid = Mail::SpamAssassin::Util::helper_app_pipe_open(*DCC,
+ $tmpf, 1, $path, "-t", "many", split(' ', $opts));
+ $pid or die "$!\n";
+ my @ignored = <DCC>;
$self->close_pipe_fh (\*DCC);
alarm(0);
@@ -334,7 +337,11 @@
$opts = $1;
}
- my $pid = open(PYZOR, join(' ', $path, $opts, "report", "< '$tmpf'", ">/dev/null 2>&1", '|')) || die "$!\n";
+ #my $pid = open(PYZOR, join(' ', $path, $opts, "report", "< '$tmpf'", ">/dev/null 2>&1", '|')) || die "$!\n";
+ my $pid = Mail::SpamAssassin::Util::helper_app_pipe_open(*PYZOR,
+ $tmpf, 1, $path, split(' ', $opts), "report");
+ $pid or die "$!\n";
+ my @ignored = <PYZOR>;
$self->close_pipe_fh (\*PYZOR);
alarm(0);
Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm (original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/Util.pm Fri Jun 18 19:03:13 2004
@@ -924,6 +924,67 @@
###########################################################################
+sub setuid_to_euid {
+ return if (RUNNING_ON_WINDOWS);
+ if ($< != $>) {
+ dbg ("setting real uid from $< to match effective uid $>");
+ $< = $>;
+ if ($< != $>) { die "setuid $< to $> failed!"; }
+ }
+}
+
+# helper app command-line open
+sub helper_app_pipe_open {
+ if (RUNNING_ON_WINDOWS) {
+ return helper_app_pipe_open_windows (@_);
+ } else {
+ return helper_app_pipe_open_unix (@_);
+ }
+}
+
+sub helper_app_pipe_open_windows {
+ my ($fh, $stdinfile, $duperr2out, @cmdline) = @_;
+
+ # use a traditional open(FOO, "cmd |")
+ my $cmd = join(' ', @cmdline);
+ if ($stdinfile) { $cmd .= " < '$stdinfile'"; }
+ if ($duperr2out) { $cmd .= " 2>&1"; }
+ return open ($fh, $cmd.'|');
+}
+
+sub helper_app_pipe_open_unix {
+ my ($fh, $stdinfile, $duperr2out, @cmdline) = @_;
+
+ # do a fork-open, so we can setuid() back
+ my $pid = open ($fh, '-|');
+ if (!defined $pid) {
+ die "cannot fork: $!";
+ }
+
+ if ($pid != 0) {
+ return $pid; # parent process; return the child pid
+ }
+
+ # else, child process. go setuid...
+ setuid_to_euid();
+ dbg ("setuid: helper proc $$: ruid=$< euid=$>");
+
+ if ($stdinfile) { # < $tmpfile
+ close STDIN;
+ open (STDIN, "<$stdinfile") or die "cannot open $stdinfile: $!";
+ }
+
+ if ($duperr2out) { # 2>&1
+ close STDERR;
+ open STDERR, ">&STDOUT" or die "dup STDOUT failed: $!";
+ }
+
+ exec @cmdline;
+ die "exec failed: $!";
+}
+
+###########################################################################
+
sub dbg { Mail::SpamAssassin::dbg (@_); }
1;
Modified: incubator/spamassassin/trunk/rules/20_html_tests.cf
==============================================================================
--- incubator/spamassassin/trunk/rules/20_html_tests.cf (original)
+++ incubator/spamassassin/trunk/rules/20_html_tests.cf Fri Jun 18 19:03:13 2004
@@ -82,13 +82,13 @@
describe HTML_TABLE_THICK_BORD HTML table has thick border
# HTML comment tests
-body HTML_COMMENT_SHORT eval:html_text('comment', '=~ /<!(?!-).{0,6}>/')
+body HTML_COMMENT_SHORT eval:html_text_match('comment', '<!(?!-).{0,6}>')
describe HTML_COMMENT_SHORT HTML comment is very short
body HTML_COMMENT_SHOUTING eval:html_test('comment_shouting')
describe HTML_COMMENT_SHOUTING HTML comment inside of "shouting" markup
-body HTML_COMMENT_SAVED_URL eval:html_text('comment', '=~ /<!-- saved from url=\(\d{4}\)/')
+body HTML_COMMENT_SAVED_URL eval:html_text_match('comment', '<!-- saved from url=\(\d{4}\)')
describe HTML_COMMENT_SAVED_URL HTML message is a saved web page
# Comment is a spam sign when following <DIV>
@@ -170,13 +170,13 @@
body HTML_JAVASCRIPT eval:html_test('javascript')
describe HTML_JAVASCRIPT JavaScript code
-body HTML_LINK_PUSH_HERE eval:html_text('anchor', '=~ /(?:push|go)\s*(?:here|this)/i')
+body HTML_LINK_PUSH_HERE eval:html_text_match('anchor', '(?i)(?:push|go)\s*(?:here|this)')
describe HTML_LINK_PUSH_HERE HTML link text says "push here" or similar
-body HTML_LINK_CLICK_HERE eval:html_text('anchor', '=~ /click\s*(?:here|this)/i')
+body HTML_LINK_CLICK_HERE eval:html_text_match('anchor', '(?i)click\s*(?:here|this)')
describe HTML_LINK_CLICK_HERE HTML link text says "click here"
-body HTML_LINK_CLICK_CAPS eval:html_text('anchor', '=~ /CLICK/')
+body HTML_LINK_CLICK_CAPS eval:html_text_match('anchor', 'CLICK')
describe HTML_LINK_CLICK_CAPS HTML link text says "CLICK"
# HTML obfuscation
@@ -290,7 +290,7 @@
describe HTML_SHORT_LENGTH HTML is extremely short
body __HTML_LENGTH_512 eval:html_eval('length', '< 512')
-body __COMMENT_EXISTS eval:html_text('comment', '=~ /<!.*?>/')
+body __COMMENT_EXISTS eval:html_text_match('comment', '<!.*?>')
meta HTML_SHORT_COMMENT (__HTML_LENGTH_512 && __COMMENT_EXISTS)
describe HTML_SHORT_COMMENT HTML is very short with HTML comments
@@ -299,13 +299,13 @@
meta HTML_SHORT_CENTER (__HTML_LENGTH_384 && __TAG_EXISTS_CENTER)
describe HTML_SHORT_CENTER HTML is very short with CENTER tag
-body HTML_TITLE_EMPTY eval:html_text('title', '!~ /\S/s')
+body HTML_TITLE_EMPTY eval:html_text_not_match('title', '(?s)\S')
describe HTML_TITLE_EMPTY HTML title contains no text
body HTML_TITLE_EXTRA eval:html_test('title_extra')
describe HTML_TITLE_EXTRA HTML has more than one title
-body HTML_TITLE_UNTITLED eval:html_text('title', '=~ /untitled|new page \d+/i')
+body HTML_TITLE_UNTITLED eval:html_text_match('title', '(?i)(?:untitled|new page \d+)')
describe HTML_TITLE_UNTITLED HTML title contains "Untitled"
###########################################################################
Modified: incubator/spamassassin/trunk/rules/20_ratware.cf
==============================================================================
--- incubator/spamassassin/trunk/rules/20_ratware.cf (original)
+++ incubator/spamassassin/trunk/rules/20_ratware.cf Fri Jun 18 19:03:13 2004
@@ -133,8 +133,8 @@
# From private mail with developers. Some top tips here!
header __THEBAT_MUA X-Mailer =~ /The Bat!/
-header __THEBAT_MUA_V1 X-Mailer =~ /^\QThe Bat! (v1.\E/
-header __THEBAT_MUA_V2 X-Mailer =~ /^\QThe Bat! (v2.\E/
+header __THEBAT_MUA_V1 X-Mailer =~ /^The Bat! \(v1\./
+header __THEBAT_MUA_V2 X-Mailer =~ /^The Bat! \(v2\./
header __CTYPE_CHARSET_QUOTED Content-Type =~ /charset=\"/i
header __CTYPE_HAS_BOUNDARY Content-Type =~ /boundary/i
header __BAT_BOUNDARY Content-Type =~ /boundary=\"?-{10}/