SA Bugzilla – Bug 1028
Spamc/spamd + ssl
Last modified: 2002-12-18 06:47:20 UTC
I wrote an ssl patch to spamc/spamd. It makes a couple of changes in order to do that: Switch from Socket.pm to IO::Socket or IO::Socket::SSL Move spamc -s to spamc -m and use -s for ssl To build with SSL support set CFLAGS to "-DSPAMC_SSL -lssl -lcrypto". I'm sure there's a better way to do this, I'm not sure how. I apologize in advance if this patch file is all messed up. Index: spamassassin-2.41/INSTALL diff -c spamassassin-2.41/INSTALL:1.1.1.1 spamassassin-2.41/INSTALL:1.2 *** spamassassin-2.41/INSTALL:1.1.1.1 Mon Sep 23 15:27:43 2002 --- spamassassin-2.41/INSTALL Wed Sep 25 14:25:43 2002 *************** *** 39,44 **** --- 39,45 ---- To install as non-root, do something like this: [unzip/untar the archive] + [add -DSPAMC_SSL to $CFLAGS to build an SSL enabled spamc] cd Mail-SpamAssassin-* perl Makefile.PL PREFIX=~/sausr SYSCONFDIR=~/saetc make Index: spamassassin-2.41/spamd/libspamc.c diff -c spamassassin-2.41/spamd/libspamc.c:1.1.1.1 spamassassin-2.41/spamd/libspamc.c:1.3 *** spamassassin-2.41/spamd/libspamc.c:1.1.1.1 Mon Sep 23 15:27:44 2002 --- spamassassin-2.41/spamd/libspamc.c Tue Sep 24 15:51:32 2002 *************** *** 19,24 **** --- 19,31 ---- #include <netdb.h> #include <arpa/inet.h> + #ifdef SPAMC_SSL + #include <openssl/crypto.h> + #include <openssl/pem.h> + #include <openssl/ssl.h> + #include <openssl/err.h> + #endif + #ifdef HAVE_SYSEXITS_H #include <sysexits.h> #endif *************** *** 346,351 **** --- 353,370 ---- int sock; float version; int response; + #ifdef SPAMC_SSL + SSL_CTX* ctx; + SSL* ssl; + SSL_METHOD *meth; + + if(flags&SPAMC_USE_SSL){ + SSLeay_add_ssl_algorithms(); + meth = SSLv2_client_method(); + SSL_load_error_strings(); + ctx = SSL_CTX_new(meth); + } + #endif m->is_spam=EX_TOOBIG; if((buf=malloc(8192))==NULL) return EX_OSERR; *************** *** 372,386 **** free(m->out); m->out=m->msg; m->out_len=m->msg_len; return i; } /* Send to spamd */ ! full_write(sock, buf, len); ! full_write(sock, m->msg, m->msg_len); ! shutdown(sock, SHUT_WR); /* Now, read from spamd */ for(len=0; len<8192; len++){ ! i=read(sock, buf+len, 1); if(i<0){ free(buf); free(m->out); m->out=m->msg; m->out_len=m->msg_len; --- 391,429 ---- free(m->out); m->out=m->msg; m->out_len=m->msg_len; return i; } + + #ifdef SPAMC_SSL + if(flags&SPAMC_USE_SSL){ + ssl = SSL_new(ctx); + SSL_set_fd(ssl, sock); + SSL_connect(ssl); + } + #endif /* Send to spamd */ ! #ifdef SPAMC_SSL ! if(flags&SPAMC_USE_SSL){ ! SSL_write(ssl, buf, len); ! SSL_write(ssl, m->msg, m->msg_len); ! } else{ ! #endif ! full_write(sock, buf, len); ! full_write(sock, m->msg, m->msg_len); ! #ifdef SPAMC_SSL ! } ! #endif /* Now, read from spamd */ for(len=0; len<8192; len++){ ! #ifdef SPAMC_SSL ! if(flags&SPAMC_USE_SSL){ ! i=SSL_read(ssl, buf+len, 1); ! } else{ ! #endif ! i=read(sock, buf+len, 1); ! #ifdef SPAMC_SSL ! } ! #endif if(i<0){ free(buf); free(m->out); m->out=m->msg; m->out_len=m->msg_len; *************** *** 416,422 **** /* Handle different versioned headers */ if(version-1.0>0.01){ for(len=0; len<8192; len++){ ! i=read(sock, buf+len, 1); if(i<=0){ free(buf); free(m->out); m->out=m->msg; m->out_len=m->msg_len; --- 459,473 ---- /* Handle different versioned headers */ if(version-1.0>0.01){ for(len=0; len<8192; len++){ ! #ifdef SPAMC_SSL ! if(flags&SPAMC_USE_SSL){ ! i=SSL_read(ssl, buf+len, 1); ! } else{ ! #endif ! i=read(sock, buf+len, 1); ! #ifdef SPAMC_SSL ! } ! #endif if(i<=0){ free(buf); free(m->out); m->out=m->msg; m->out_len=m->msg_len; *************** *** 445,451 **** } /* Should be end of headers now */ ! if(full_read(sock, buf, 2, 2)!=2 || buf[0]!='\r' || buf[1]!='\n'){ /* Nope, bail. */ free(buf); free(m->out); m->out=m->msg; m->out_len=m->msg_len; --- 496,511 ---- } /* Should be end of headers now */ ! #ifdef SPAMC_SSL ! if(flags&SPAMC_USE_SSL){ ! i=SSL_read(ssl, buf, 2); ! } else{ ! #endif ! i=read(sock, buf, 2); ! #ifdef SPAMC_SSL ! } ! #endif ! if(i!=2 || buf[0]!='\r' || buf[1]!='\n'){ /* Nope, bail. */ free(buf); free(m->out); m->out=m->msg; m->out_len=m->msg_len; *************** *** 465,478 **** return EX_PROTOCOL; } ! len=full_read(sock, m->out+m->out_len, m->max_len+EXPANSION_ALLOWANCE+1-m->out_len, m->max_len+EXPANSION_ALLOWANCE+1-m->out_len); if(len+m->out_len>m->max_len+EXPANSION_ALLOWANCE){ free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_TOOBIG; } m->out_len+=len; ! shutdown(sock, SHUT_RD); if(m->out_len!=expected_len){ syslog(LOG_ERR, "failed sanity check, %d bytes claimed, %d bytes seen", expected_len, m->out_len); --- 525,552 ---- return EX_PROTOCOL; } ! #ifdef SPAMC_SSL ! if(flags&SPAMC_USE_SSL){ ! len=SSL_read(ssl, m->out+m->out_len, m->max_len+EXPANSION_ALLOWANCE+1-m->out_len); ! } else{ ! #endif ! len=read(sock, m->out+m->out_len, m->max_len+EXPANSION_ALLOWANCE+1-m->out_len); ! #ifdef SPAMC_SSL ! } ! #endif if(len+m->out_len>m->max_len+EXPANSION_ALLOWANCE){ free(m->out); m->out=m->msg; m->out_len=m->msg_len; return EX_TOOBIG; } m->out_len+=len; ! close(sock); ! #ifdef SPAMC_SSL ! if(flags&SPAMC_USE_SSL){ ! SSL_free(ssl); ! SSL_CTX_free(ctx); ! } ! #endif if(m->out_len!=expected_len){ syslog(LOG_ERR, "failed sanity check, %d bytes claimed, %d bytes seen", expected_len, m->out_len); Index: spamassassin-2.41/spamd/libspamc.h diff -c spamassassin-2.41/spamd/libspamc.h:1.1.1.1 spamassassin-2.41/spamd/libspamc.h:1.2 *** spamassassin-2.41/spamd/libspamc.h:1.1.1.1 Mon Sep 23 15:27:44 2002 --- spamassassin-2.41/spamd/libspamc.h Tue Sep 24 15:51:32 2002 *************** *** 26,31 **** --- 26,32 ---- #define SPAMC_RAW_MODE 0 #define SPAMC_BSMTP_MODE 1 + #define SPAMC_USE_SSL 1<<29 #define SPAMC_SAFE_FALLBACK 1<<30 #define SPAMC_CHECK_ONLY 1<<31 Index: spamassassin-2.41/spamd/spamc.c diff -c spamassassin-2.41/spamd/spamc.c:1.1.1.1 spamassassin-2.41/spamd/spamc.c:1.3 *** spamassassin-2.41/spamd/spamc.c:1.1.1.1 Mon Sep 23 15:27:44 2002 --- spamassassin-2.41/spamd/spamc.c Wed Sep 25 14:44:05 2002 *************** *** 65,72 **** printf("-e command [args]: Command to output to instead of stdout. MUST BE THE LAST OPTION.\n"); printf("-f: fallback safely - in case of comms error, dump original message unchanges instead of setting exitcode\n"); printf("-h: print this help message\n"); printf("-p port: specify port for connection [default: 783]\n"); ! printf("-s size: specify max message size, any bigger and it will be returned w/out processing [default: 250k]\n"); printf("-u username: specify the username for spamd to process this message under\n"); } --- 65,73 ---- printf("-e command [args]: Command to output to instead of stdout. MUST BE THE LAST OPTION.\n"); printf("-f: fallback safely - in case of comms error, dump original message unchanges instead of setting exitcode\n"); printf("-h: print this help message\n"); + printf("-m size: specify max message size, any bigger and it will be returned w/out processing [default: 250k]\n"); printf("-p port: specify port for connection [default: 783]\n"); ! printf("-s: use SSL to talk to spamd\n"); printf("-u username: specify the username for spamd to process this message under\n"); } *************** *** 75,81 **** { int opt, i, j; ! while(-1 != (opt = getopt(argc,argv,"-Bcd:e:fhp:t:s:u:"))) { switch(opt) { --- 76,82 ---- { int opt, i, j; ! while(-1 != (opt = getopt(argc,argv,"-Bcd:e:fhsp:t:u:m:"))) { switch(opt) { *************** *** 119,127 **** *username = optarg; break; } ! case 's': { *max_size = atoi(optarg); break; } case '?': { --- 120,133 ---- *username = optarg; break; } ! case 'm': { *max_size = atoi(optarg); + break; + } + case 's': + { + flags |= SPAMC_USE_SSL; break; } case '?': { Index: spamassassin-2.41/spamd/spamc.pod diff -c spamassassin-2.41/spamd/spamc.pod:1.1.1.1 spamassassin-2.41/spamd/spamc.pod:1.2 *** spamassassin-2.41/spamd/spamc.pod:1.1.1.1 Mon Sep 23 15:27:44 2002 --- spamassassin-2.41/spamd/spamc.pod Wed Sep 25 14:23:02 2002 *************** *** 7,13 **** =over ! =item spamc [-c] [-d host] [-f] [-h] [-p port] [-s max_size] [-u username] [-e command [args]] =back --- 7,13 ---- =over ! =item spamc [-c] [-d host] [-f] [-h] [-s] [-p port] [-m max_size] [-u username] [-e command [args]] =back *************** *** 60,70 **** Print this help message and terminate without action =item B<-p> I<port> Connect to spamd server listening on given port ! =item B<-s> I<max_size> Set the maximum message size which will be sent to spamd -- any bigger than this threshold and the message will be returned unprocessed. Note that the --- 60,74 ---- Print this help message and terminate without action + =item B<-s> + + Encrypt data to and from the spamd server with SSL + =item B<-p> I<port> Connect to spamd server listening on given port ! =item B<-m> I<max_size> Set the maximum message size which will be sent to spamd -- any bigger than this threshold and the message will be returned unprocessed. Note that the Index: spamassassin-2.41/spamd/spamd.raw diff -c spamassassin-2.41/spamd/spamd.raw:1.1.1.1 spamassassin-2.41/spamd/spamd.raw:1.8 *** spamassassin-2.41/spamd/spamd.raw:1.1.1.1 Mon Sep 23 15:27:44 2002 --- spamassassin-2.41/spamd/spamd.raw Wed Sep 25 14:43:48 2002 *************** *** 12,18 **** use lib '../lib'; # added by jm for use inside the distro use strict; ! use Socket; use Carp; use Config; use Mail::SpamAssassin; --- 12,20 ---- use lib '../lib'; # added by jm for use inside the distro use strict; ! use IO::Socket; ! use IO::Handle; use Carp; use Config; use Mail::SpamAssassin; *************** *** 48,53 **** --- 50,58 ---- my @OLD_ARGV = @ARGV; # Getopt::Long tends to clear @ARGV Getopt::Long::Configure ("bundling"); GetOptions( + 'server-key=s' => \$opt{'server-key'}, + 'server-cert=s' => \$opt{'server-cert'}, + 'ssl' => \$opt{'ssl'}, 'auto-whitelist|whitelist|a' => \$opt{'auto-whitelist'}, 'create-prefs!', => \$opt{'create-prefs'}, 'c' => \$opt{'create-prefs'}, 'daemonize!' => \$opt{'daemonize'}, 'd' => \$opt{'daemonize'}, *************** *** 79,84 **** --- 84,107 ---- $opt{'help'} and pod2usage(-exitval => $resphash{'EX_USAGE'}, -verbose => 0, -message => 'For more details, use "man spamd"'); + # Check for server certs + $opt{'server-key'} ||= "$LOCAL_RULES_DIR/certs/server-key.pem"; + $opt{'server-cert'} ||= "$LOCAL_RULES_DIR/certs/server-cert.pem"; + if ($opt{'ssl'}) + { + require IO::Socket::SSL; + + if (!-e $opt{'server-key'}) + { + die "The server key file $opt{'server-key'} does not exist"; + } + if (!-e $opt{'server-cert'}) + { + die "The server certificate file $opt{'server-cert'} does not exist"; + } + } + # These can be changed on command line with -A flag if(@{$opt{'allowed-ip'}}) { *************** *** 138,153 **** setlogsock($socktype) unless $log_facility eq 'stderr'; my $port = $opt{'port'} || 783; ! my $addr = gethostbyname($opt{'listen-ip'} || '127.0.0.1'); my $proto = getprotobyname('tcp'); ($port) = $port =~ /^(\d+)$/ or die "invalid port"; # Be a well-behaved daemon ! socket(Server, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; ! setsockopt(Server,SOL_SOCKET,SO_REUSEADDR,pack("l",1)) || die "setsockopt: $!"; ! bind(Server, sockaddr_in($port, $addr)) || die "bind: $!"; ! listen(Server,SOMAXCONN) || die "listen: $!"; $opt{'daemonize'} and daemonize(); --- 161,196 ---- setlogsock($socktype) unless $log_facility eq 'stderr'; my $port = $opt{'port'} || 783; ! my $addr = (gethostbyname($opt{'listen-ip'} || '127.0.0.1'))[0]; my $proto = getprotobyname('tcp'); ($port) = $port =~ /^(\d+)$/ or die "invalid port"; # Be a well-behaved daemon ! my $server; ! if ($opt{'ssl'}) ! { ! $server = new IO::Socket::SSL(LocalAddr => $addr, ! LocalPort => $port, ! Proto => $proto, ! Type => SOCK_STREAM, ! ReuseAddr => 1, ! Listen => 5, ! SSL_verify_mode => 0x00, ! SSL_key_file => $opt{'server-key'}, ! SSL_cert_file => $opt{'server-cert'}) ! || die "new IO::Socket::SSL: $! $@"; ! } ! else ! { ! $server = new IO::Socket::INET(LocalAddr => $addr, ! LocalPort => $port, ! Proto => $proto, ! Type => SOCK_STREAM, ! ReuseAddr => 1, ! Listen => 10) ! || die "new IO::Socket::INET: $! $@"; ! } $opt{'daemonize'} and daemonize(); *************** *** 205,210 **** --- 248,254 ---- my $current_user; my $paddr; + my $client; sub REAPER { # Adapted from the perlipc manpage cleanupchildren; *************** *** 227,238 **** } logmsg "server started on port $port (running version ".Mail::SpamAssassin::Version().")"; ! for ( ; ($paddr = accept(Client,Server)) ; close Client) { ! my $start = time; ! my($port,$iaddr) = sockaddr_in($paddr); my $name = gethostbyaddr($iaddr,AF_INET); if (ip_is_allowed(inet_ntoa($iaddr))) { --- 271,283 ---- } logmsg "server started on port $port (running version ".Mail::SpamAssassin::Version().")"; ! while (1) { ! $client = $server->accept ! || next; my $start = time; ! my($port,$iaddr) = sockaddr_in($client->peername); my $name = gethostbyaddr($iaddr,AF_INET); if (ip_is_allowed(inet_ntoa($iaddr))) { *************** *** 241,257 **** } else { logmsg "unauthorized connection from $name [", inet_ntoa($iaddr),"] at port $port"; next; } spawn sub { $|=1; # always immediately flush output # First request line off stream ! local $_ = <STDIN>; if (!defined $_) { ! protocol_error ("(closed before headers)"); return 1; } --- 286,305 ---- } else { logmsg "unauthorized connection from $name [", inet_ntoa($iaddr),"] at port $port"; + $client->close; next; } spawn sub { $|=1; # always immediately flush output + my ($client) = @_; + # First request line off stream ! local $_ = <$client>; if (!defined $_) { ! protocol_error ("(closed before headers)", $client); return 1; } *************** *** 285,294 **** { while(1) { ! $_ = <STDIN>; if(!defined $_) { ! protocol_error ("(EOF during headers)"); return 1; } --- 333,342 ---- { while(1) { ! $_ = <$client>; if(!defined $_) { ! protocol_error ("(EOF during headers)", $client); return 1; } *************** *** 348,354 **** my $actual_length; my $in_header = 1; my $msgid; ! for (<STDIN>) { if ($in_header) { if (/^$/) { $in_header = 0; --- 396,402 ---- my $actual_length; my $in_header = 1; my $msgid; ! while (<$client>) { if ($in_header) { if (/^$/) { $in_header = 0; *************** *** 363,368 **** --- 411,417 ---- } push(@msglines, $_); $actual_length += length; + last if $actual_length == $expected_length; } logmsg "checking message $msgid for $current_user:$>" . *************** *** 403,411 **** { $response_header .= "Spam: False ; $msg_score / $msg_threshold"; } ! print $response_header, "\r\n\r\n"; ! print $status->get_names_of_tests_hit,"\r\n" if ($method eq "SYMBOLS"); ! print $status->get_report,"\r\n" if ($method eq "REPORT" or $method eq "REPORT_IFSPAM" and $status->is_spam); $current_user ||= '(unknown)'; logmsg "$was_it_spam ($msg_score/$msg_threshold) for $current_user:$> in ". sprintf("%3d", time - $start) ." seconds, $actual_length bytes.\n"; --- 452,460 ---- { $response_header .= "Spam: False ; $msg_score / $msg_threshold"; } ! print $client $response_header, "\r\n\r\n"; ! print $client $status->get_names_of_tests_hit,"\r\n" if ($method eq "SYMBOLS"); ! print $client $status->get_report,"\r\n" if ($method eq "REPORT" or $method eq "REPORT_IFSPAM" and $status->is_spam); $current_user ||= '(unknown)'; logmsg "$was_it_spam ($msg_score/$msg_threshold) for $current_user:$> in ". sprintf("%3d", time - $start) ." seconds, $actual_length bytes.\n"; *************** *** 429,438 **** { while(1) { ! $_ = <STDIN>; if(!defined $_) { ! protocol_error ("(EOF during headers)"); return 1; } --- 478,487 ---- { while(1) { ! $_ = <$client>; if(!defined $_) { ! protocol_error ("(EOF during headers)", $client); return 1; } *************** *** 492,498 **** my $actual_length; my $in_header = 1; my $msgid; ! for (<STDIN>) { if ($in_header) { if (/^$/) { $in_header = 0; --- 541,547 ---- my $actual_length; my $in_header = 1; my $msgid; ! while (<$client>) { if ($in_header) { if (/^$/) { $in_header = 0; *************** *** 507,512 **** --- 556,562 ---- } push(@msglines, $_); $actual_length += length; + last if $actual_length == $expected_length; } logmsg "processing message $msgid for $current_user:$>" . *************** *** 519,525 **** # Check length if we're supposed to if($expected_length) { ! if($actual_length != $expected_length) { protocol_error ("(Content-length mismatch: $expected_length vs. $actual_length)"); return 1; } } # Now use copy-on-writed (hopefully) SA object --- 569,576 ---- # Check length if we're supposed to if($expected_length) { ! if($actual_length != $expected_length) { ! protocol_error ("(Content-length mismatch: $expected_length vs. $actual_length)", $client); return 1; } } # Now use copy-on-writed (hopefully) SA object *************** *** 531,543 **** my $msg_resp_length = length($msg_resp); if($version >= 1.2) # Spamc protocol 1.2 means it accepts content-length { ! print "SPAMD/1.1 $resphash{$resp} $resp\r\n", "Content-length: $msg_resp_length\r\n\r\n", $msg_resp; } else # Earlier than 1.2 didn't accept content-length { ! print "SPAMD/1.0 $resphash{$resp} $resp\r\n", $msg_resp; } my $was_it_spam; --- 582,594 ---- my $msg_resp_length = length($msg_resp); if($version >= 1.2) # Spamc protocol 1.2 means it accepts content-length { ! print $client "SPAMD/1.1 $resphash{$resp} $resp\r\n", "Content-length: $msg_resp_length\r\n\r\n", $msg_resp; } else # Earlier than 1.2 didn't accept content-length { ! print $client "SPAMD/1.0 $resphash{$resp} $resp\r\n", $msg_resp; } my $was_it_spam; *************** *** 555,561 **** else { ! protocol_error ($_); } }; --- 606,612 ---- else { ! protocol_error ($_, $client); } }; *************** *** 566,578 **** # essentially does this! cleanupchildren; } sub protocol_error { local $_ = shift; my $resp = "EX_PROTOCOL"; ! print "SPAMD/1.0 $resphash{$resp} Bad header line: $_\r\n"; logmsg "bad protocol: header error: $_"; } --- 617,631 ---- # essentially does this! cleanupchildren; + $client->close; } sub protocol_error { local $_ = shift; + my $client = shift; my $resp = "EX_PROTOCOL"; ! print $client "SPAMD/1.0 $resphash{$resp} Bad header line: $_\r\n"; logmsg "bad protocol: header error: $_"; } *************** *** 605,614 **** } # else I'm the child -- go spawn ! close Server; ! open(STDIN, "<&Client") || die "can't dup client to stdin"; ! open(STDOUT, ">&Client") || die "can't dup client to stdout"; ! exit &$coderef(); } sub handle_user --- 658,667 ---- } # else I'm the child -- go spawn ! $server->close; ! exit &$coderef($client); } sub handle_user *************** *** 773,779 **** { my ($sig) = @_; logmsg "server killed by SIG$sig, shutting down"; ! close Server; defined($opt{'pidfile'}) and unlink($opt{'pidfile'}); exit 0; } --- 826,832 ---- { my ($sig) = @_; logmsg "server killed by SIG$sig, shutting down"; ! $server->close; defined($opt{'pidfile'}) and unlink($opt{'pidfile'}); exit 0; } *************** *** 855,860 **** --- 908,916 ---- -V, --virtual-config=dir Enable Virtual configs (needs -x) -r pidfile, --pidfile Write the process id to pidfile -s facility, --syslog=facility Specify the syslog facility (default: mail) + --server-key keyfile Specify an SSL keyfile + --server-cert certfile Specify an SSL certificate + --ssl Run an SSL server -u username, --username=username Run as username -v, --vpopmail Enable vpopmail config -x, --nouser-config Disable user config files
Sounds interesting. Could you please re-generate the diff in unified format (with -u) and attach it to this bug via "Create a new attachment". Please split the patch in three files: One for libspamc, one for spamd part and one containing the changes for INSTALL et al. Two things disturb me on the first glance: * -s shouldn't change it's meaning. Use -S for SSL. * I don't know if IO::Socket is shipped with Perl. If not, it would be nice if SA fell back to Socket.pm if IO::Socket is not available.
Created attachment 357 [details] Patch to INSTALL
Created attachment 358 [details] Patch to libspamc.c
Created attachment 359 [details] Patch to spamc.c
Created attachment 360 [details] Patch to spamc.pod
Created attachment 361 [details] Patch to spamd
> Sounds interesting. Could you please re-generate the diff in unified format > (with -u) and attach it to this bug via "Create a new attachment". Please > split the patch in three files: One for libspamc, one for spamd part and one > containing the changes for INSTALL et al. Done. > Two things disturb me on the first glance: > * -s shouldn't change it's meaning. Use -S for SSL. Good call, I made the switch > * I don't know if IO::Socket is shipped with Perl. If not, it would be nice if > SA fell back to Socket.pm if IO::Socket is not available. IO::Socket's been part of the 5.? standard package as long as I can see. Anyone with an install newer then 1997 should have it for sure.
Seems like IO::Socket was shipped with 5.6.1. It wasn't shipped with 5.005 but that doesn't matter as it didn't ship Socket.pm, too ;-) I'll have a deeper look into your patch(es) tomorrow.
Okay, first the patch... - Please attach patches as attachments, not cut-and-paste. (I think Malte covered this.) - Since changes are all related, one patch would be preferred over the split-up version. It's easier to download and if someone (Malte) wants a split-up version, he can just run diffsplit. Also, if you end-up with several versions of the patch, I don't really want there to be 5 * (number of versions) attachments. Okay, it's perhaps Malte's call since he took the bug, but I think you're much less likely to get review from other developers by splitting up the patch into a zillion attachments. Malte, perhaps you'd be interested in my diffsplit tool: http://www.pathname.com/~quinlan/software/diffsplit/diffsplit "cvsdiff" is a related useful tool for generating correct CVS diffs: http://www.pathname.com/~quinlan/software/cvsdiff/cvsdiff :-) Now for the general comments: How much load does SSL add to the spamd server? It seems like it would be less expensive and more economical to run spamd inside your firewall. Or perhaps I should ask why it's better/economical to run spamd outside your firewall?
> Now for the general comments: > How much load does SSL add to the spamd server? It seems like it would be > less expensive and more economical to run spamd inside your firewall. Or > perhaps I should ask why it's better/economical to run spamd outside your > firewall? Not a lot. I haven't done any real tests, but it takes about the same amout of time to talk to an ssl server as it does to talk to a regular one. Other daemons I've ssl-atized haven't seen big performance hits. As for the firewall, unless you're running a "deny all" type setup you're still running the risk of intruders. Even the best firewall doesn't protect you from people on the inside. At a site like ours (8500 users, 1500+ computers) the internal threat is often the bigger one. I wrote the path because we don't send anything in the clear over the network if we can help it. Most people probably aren't so picky, but they don't have to use SSL if they don't want to.
Dan: Thanks for the links, very helpful ;-) I hoped to get three patches, one for spamc, one for spamd and one for the rest but maybe I wasn't very clear in this point. Nate is probably right: It's a "use it or leave it" option for the paranoid. I'll backport the patch to my local 2.42-cvs installation and test it thoroughly before I commit it to HEAD.
Subject: Re: [SAdev] Spamc/spamd + ssl spamassassin-contrib@msquadrat.de wrote: > Dan: Thanks for the links, very helpful ;-) I hoped to get three > patches, one for spamc, one for spamd and one for the rest but maybe > I wasn't very clear in this point. Well, they are helpful. :-) I should probably post my "cvslog" script. It's very nice too. > Nate is probably right: It's a "use it or leave it" option for the > paranoid. I'll backport the patch to my local 2.42-cvs installation > and test it thoroughly before I commit it to HEAD. I have no objections to the patch, paranoia is a good thing. I'm still a bit foggy on why people want to run spamd/spamc from one machine to another, though. :-) Dan
> I'm still a bit foggy on why people want to run spamd/spamc from one > machine to another, though. :-) Some kind of load balancing? Just a guess :-]
Yeah, load balancing is important. I know of one site using spamassassin to filter mail on an SMTP gateway for 350,000 mailboxes spread across about 50 companies. There's just no way you can process that volume of traffic on a single box.
> I'm still a bit foggy on why people want to run spamd/spamc from one > machine to another, though. :-) We have people receiving mail on over 100 different computers. It's a lot easier for us to maintain one spamd then keep it running all over the department.
The mailserver/firewall here has 8Mb of RAM in total; spamassassin / spamd's working set is over twice that size, so it couldn't run SA at all without spamd. With spamd, everything is just peachy; spamc has a tiny memory requirement, and spamd can run on a box with more memory (about a hundred times as much) behind the firewall.
Malte, what's the status on this?
ok, now in (sorry Malte ;)