From c3c8a5107d39e3b7980d5aa25ad77cacd8b77085 Mon Sep 17 00:00:00 2001 From: mpaperno Date: Thu, 30 Aug 2012 00:01:15 -0400 Subject: Old versions archived. --- previous-versions/spampd-0.0.1.pl | 523 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 523 insertions(+) create mode 100644 previous-versions/spampd-0.0.1.pl (limited to 'previous-versions/spampd-0.0.1.pl') diff --git a/previous-versions/spampd-0.0.1.pl b/previous-versions/spampd-0.0.1.pl new file mode 100644 index 0000000..4d0e598 --- /dev/null +++ b/previous-versions/spampd-0.0.1.pl @@ -0,0 +1,523 @@ +#!/usr/bin/perl -w + +############################################################ +# This code is a merging of spamd (copyright 2001 by Craig Hughes) +# and spamproxyd by Ian R. Justman. +# Like spamproxyd, it is written with Postfix "advanced" content +# filtering in mind. See FILTER_README in the Postfix distribution +# for more information on how to set this up. +# +# The primary difference between spamproxyd and spampd is that +# spampd acutally tags the spams and sends them on, even making +# use of the auto-whitelist feature (and soon the SQL lookups +# based on the recipient email address, maybe). +# +# The primary difference between spamd and spampd is that spampd +# talks SMTP protocol for its I/O stream (via Net::SMTP::Server +# and Mail::SpamAssassin::SMTP::SmartHost). +# +# WARNING: Use at your own risk. Basically I have no idea what +# I'm doing with the process forking stuff, I just copied it and +# messed around until it worked (for me, YMMV). Also the demonizing +# stuff seems screwy when you go to kill the daemon (at least via inet.d +# script), but it does exit and clean up so no harm seems to be done. +# +# Development/production environment is RH Linux 7.x on various x86 hardware. +# +# BUG: for some reason the log and warn (if -D) messages don't print during +# SIGTERM or when a child dies (after processing it's allotted # of msgs). +# I have no idea why (see above) +# +# spampd is licensed for use under the terms of the Perl Artistic License +# +############################################################ + +# use lib '../lib'; # added by jm for use inside the distro +use strict; +# use Socket; +use Carp; +use Net::SMTP::Server; +use Net::SMTP::Server::Client; +use Mail::SpamAssassin; +use Mail::SpamAssassin::NoMailAudit; +use Mail::SpamAssassin::SMTP::SmartHost; +use Net::DNS; +use Sys::Syslog qw(:DEFAULT setlogsock); +use POSIX qw(setsid); +use Getopt::Std; +use POSIX ":sys_wait_h"; + +my %resphash = ( + EX_OK => 0, # no problems + EX_USAGE => 64, # command line usage error + EX_DATAERR => 65, # data format error + EX_NOINPUT => 66, # cannot open input + EX_NOUSER => 67, # addressee unknown + EX_NOHOST => 68, # host name unknown + EX_UNAVAILABLE => 69, # service unavailable + EX_SOFTWARE => 70, # internal software error + EX_OSERR => 71, # system error (e.g., can't fork) + EX_OSFILE => 72, # critical OS file missing + EX_CANTCREAT => 73, # can't create (user) output file + EX_IOERR => 74, # input/output error + EX_TEMPFAIL => 75, # temp failure; user is invited to retry + EX_PROTOCOL => 76, # remote error in protocol + EX_NOPERM => 77, # permission denied + EX_CONFIG => 78, # configuration error + ); + +sub usage +{ + warn <new({ + dont_copy_prefs => $dontcopy, + local_tests_only => $opt_L, + debug => $opt_D, + paranoid => ($opt_P || 0), +}); + +$opt_w and eval +{ + require Mail::SpamAssassin::DBBasedAddrList; + + # create a factory for the persistent address list + my $addrlistfactory = Mail::SpamAssassin::DBBasedAddrList->new(); + $spamtest->set_persistent_address_list_factory ($addrlistfactory); +}; + +sub logmsg; # forward declaration + +setlogsock('unix'); + +# Use Net::SMTP::Server here to talk regular SMTP +my $server = new Net::SMTP::Server($addr, $port) || + die "Unable to create server: $! : $addr, $port\n"; + +# support non-root use (after we bind to the port) +my $setuid_to_user = 0; +if ($opt_u) { + my $uuid = getpwnam($opt_u); + if (!defined $uuid || $uuid == 0) { + die "fatal: cannot run as nonexistent user or root with -u option\n"; + } + $> = $uuid; # effective uid + $< = $uuid; # real uid. we now cannot setuid anymore + if ($> != $uuid) { + die "fatal: setuid to uid $uuid failed\n"; + } +} + +$spamtest->compile_now(); # ensure all modules etc. are loaded +$/ = "\n"; # argh, Razor resets this! Bad Razor! + +$opt_d and daemonize(); + +my $current_user; + +if ($opt_D) { + warn "server started on port $port\n"; + warn "server pid: $$\n"; +} +logmsg "server started on $addr:$port; server pid: $$\n"; + +# Ian R. Justman writes in spamproxyd: +# This is the preforking and option-parsiong section taken from the MSDW +# smtpproxy code by Bennett Todd. Any comments from that code are not my +# own comments (marked with "[MSDW]") unless otherwise noted. +# +# Depending on your platform, you may need his patch which uses +# IPC/semaphores to get information which may be required to allow two +# simultaneous instances to accept() a connection, which can be obtained at +# http://bent.latency.net/smtpprox/smtpprox-semaphore-patch. It is best to +# apply the patch to the original script, then port it to this one. +# +# --irj + +# [MSDW] +# This should allow a kill on the parent to also blow away the +# children, I hope +my %children; +use vars qw($please_die); +$please_die = 0; +$SIG{INT} = sub { $please_die = 1; }; +$SIG{TERM} = sub { $please_die = 1; }; # logmsg "server killed by SIGTERM, shutting down"; + +# [MSDW] +# This sets up the parent process + +PARENT: while (1) { + while (scalar(keys %children) >= $children) { + my $child = wait; + delete $children{$child} if exists $children{$child}; + if ($please_die) { kill 15, keys %children; exit 0; } + } + my $pid = fork; + die "$0: fork failed: $!\n" unless defined $pid; + last PARENT if $pid == 0; + $children{$pid} = 1; + select(undef, undef, undef, 0.1); + if ($please_die) { kill 15, keys %children; exit 0; } +} + +# [MSDW] +# This block is a child service daemon. It inherited the bound +# socket created by SMTP::Server->new, it will service a random +# number of connection requests in [minperchild..maxperchild] then +# exit + +my $lives = $minperchild + (rand($maxperchild - $minperchild)); + +while(my $conn = $server->accept()) { + + my $client = new Net::SMTP::Server::Client($conn) || + next; + + my $start = time; + + # [MSDW] + # Process the client. This command will block until + # the connecting client completes the SMTP transaction. + $client->process || next; + +# we'll have to revisit this later +# if ($opt_q) { +# handle_user_sql($1); +# } + + my $resp = "EX_OK"; + + # Now read in message + my $message = $client->{MSG}; + my @msglines = split ("\r\n", $message); + my $arraycont = @msglines; for(0..$arraycont) { $msglines[$_] .= "\r\n"; } + # Audit the message + my $mail = Mail::SpamAssassin::NoMailAudit->new ( + data => \@msglines, + add_From_line => $opt_F + ); + + # Check spamminess and rewrite mail if high spam factor or option -a (tag All) + my $status = $spamtest->check($mail); + if ( $status->is_spam || $opt_a ) { + $status->rewrite_mail; + } + + # Build the message to send back + my $msg_resp = join '',$mail->header,"\n",@{$mail->body}; + + # Relay the (rewritten) message through perl SmartHost module + my $relay = new Mail::SpamAssassin::SMTP::SmartHost($client->{FROM}, + $client->{TO}, + $msg_resp, + "$smarthost", + "$myhelo"); + + # Log what we did, FWIW + my $was_it_spam; + if($status->is_spam) { $was_it_spam = 'identified spam'; } else { $was_it_spam = 'clean message'; } + my $msg_score = int($status->get_hits); + my $msg_threshold = int($status->get_required_hits); + #$current_user ||= '(unknown)'; + logmsg "$was_it_spam ($msg_score/$msg_threshold) in ". + sprintf("%3d", time - $start) ." seconds.\n"; + + $status->finish(); # added by jm to allow GC'ing + + # Zap this instance if this child's processing limit has been reached. + # --irj + delete $server->{"s"}; + if ($lives-- <= 0) { + if ($opt_D) { + warn "killing child process\n"; + } + exit 0; + } +} + +sub handle_user_sql +{ + $current_user = shift; + $spamtest->load_scoreonly_sql ($current_user); + return 1; +} + +sub logmsg +{ + openlog('spamd','cons,pid',$log_facility); + syslog('info',"@_"); + if ($opt_D) { warn "logmsg: @_\n"; } +} + +sub kill_handler +{ + my ($sig) = @_; + logmsg "server killed by SIG$sig, shutting down"; + $please_die = 1; + return 1; + #close Server; + #exit 0; +} + +use POSIX 'setsid'; +sub daemonize +{ + chdir '/' or die "Can't chdir to '/': $!"; + open STDIN,'/dev/null' or die "Can't read '/dev/null': $!"; + open STDOUT,'>/dev/null' or die "Can't write '/dev/null': $!"; + defined(my $pid=fork) or die "Can't fork: $!"; + exit if $pid; + setsid or die "Can't start new session: $!"; + open STDERR,'>&STDOUT' or die "Can't duplicate stdout: $!"; +} + +=head1 NAME + +spampd - daemonized version of spamassassin with SMTP IO interface + +=head1 SYNOPSIS + +spampd [options] + +=head1 OPTIONS + +=over + +=item B<-w> + +Use auto-whitelists. These will automatically create a list of +senders whose messages are to be considered non-spam by monitoring the total +number of received messages which weren't tagged as spam from that sender. +Once a threshold is exceeded, further messages from that sender will be given a +non-spam bonus (in case you correspond with people who occasionally swear in +their emails). + +=item B<-a> + +Tag All messages with SpamAssassin X-Spam-Status header, even if non spam. Default +is to tag spam only. + +=item B<-d> + +Detach from starting process and run in background (daemonize). + +=item B<-h> + +Print a brief help message, then exit without further action. + +=item B<-i> I + +Tells spamd to listen on the specified IP address [defaults to 127.0.0.1]. Use +0.0.0.0 to listen on all interfaces. + +=item B<-p> I + +Optionally specifies the port number for the server to listen on. + +=item B<-t> I + +Use specified IP address as relay (To) host (default: 127.0.0.1) + +=item B<-v> I + +Use specified port on the relay host specified with -t (default: 10026) + +=item B<-g> I + +Use specified hostname in the SMTP HELO greeting to the relay host (default: spamfilter.localdomain) + +=item B<-q> + +Turn on SQL lookups even when per-user config files have been disabled +with B<-x>. this is useful for spamd hosts which don't have user's +home directories but do want to load user preferences from an SQL +database. + +=item B<-s> I + +Specify the syslog facility to use (default: mail). + +=item B<-u> I + +Run as the named user. The alternative, default behaviour is to setuid() to +the user running C, if C is running as root. + +=item B<-D> + +Print debugging messages + +=item B<-C> + +Number of child processes to create (Default: 4) + +=item B<-m> + +Minumum number of connections to handle per child before exiting (Default: 5) + +=item B<-M> + +Maximum number of connections to handle per child before exiting (Default: 10) + +=item B<-L> + +Perform only local tests on all mail. In other words, skip DNS and other +network tests. Works the same as the C<-L> flag to C. + +=item B<-P> + +Die on user errors (for the user passed from spamc) instead of falling back to +user I and using the default configuration. + +=item B<-F> I<0 | 1> + +Ensure that the output email message either always starts with a 'From ' line +(I<1>) for UNIX mbox format, or ensure that this line is stripped from the +output (I<0>). (default: 1) + +=back + +=head1 DESCRIPTION + +The purpose of this program is to provide a daemonized version of the +spamassassin executable. The goal is improving throughput performance for +automated mail checking. + +This version uses SMTP as the I/O transport. It is inteded to be used as a +Postfix content_filter or other transport agent. + +This code is a merging of spamd (copyright 2001 by Craig Hughes) +and spamproxyd by Ian R. Justman. +Like spamproxyd, it is written with Postfix "advanced" content +filtering in mind. See FILTER_README in the Postfix distribution +for more information on how to set this up. + +The primary difference between spamproxyd and spampd is that +spampd acutally tags the spams and sends them on, even making +use of the auto-whitelist feature (and soon the SQL lookups +based on the recipient email address, maybe). + +The primary difference between spamd and spampd is that spampd +talks SMTP protocol for its I/O stream (via Net::SMTP::Server +and Mail::SpamAssassin::SMTP::SmartHost). + +WARNING: Use at your own risk. Basically I have no idea what +I'm doing with the process forking stuff, I just copied it and +messed around until it worked (for me, YMMV). Also the demonizing +stuff seems screwy when you go to kill the daemon (at least via inet.d +script), but it does exit and clean up so no harm seems to be done. + +Development/production environment is RH Linux 7.x on various x86 hardware. + +BUG: for some reason the log and warn (if -D) messages don't print during +SIGTERM or when a child dies (after processing it's allotted # of msgs). +I have no idea why (see above) + +=head1 SEE ALSO + +spamassassin(1) +Mail::SpamAssassin(3) + +=head1 AUTHOR + +Maxim Paperno EMPaperno@worldDesign.comE + +=head1 CREDITS + +Justin Mason and Craig Hughes for B +and B + +Ian R. Justman for his B implementation + +Habeeb J. "MacGyver" Dihu for his B code + +Bennett Todd for the perforking code and option-parsing code from his + pacakge, smtpproxy (used via spamproxyd code) + +=head1 PREREQUISITES + +C +C + +=cut -- cgit v1.2.3-24-g4f1b