I've whipped up a little patch that enables ident-based authentication
for spamd/spamc.  That is, spamd uses ident to verify that spamc is
really being run by the user it claims to be running on the behalf of.

I'm interested in comments on this code.  Currently, it requires
Net::Ident (available from CPAN) but fails nicely (ie., loudly) when
it's not present AND --auth-ident is used.  I used --auth-ident
anticipating that other authentication methods may be add later.

The patch provided here is for the current cvs version of spamd.raw,
but a backport to 2.43 is available here:

http://www.dulug.duke.edu/~mstenner/spamassassin/auth-ident/

                                        -Michael

P.S. I intend to look into a unix-socket-based spamc/spamd connection
that would also allow user authentication.  Preliminary poking around
suggests that will be much more difficult, so we'll see.

P.P.S. If the cross-posting is inappropriate here, just tell me which
way I should go :)

-- 
  Michael Stenner                       Office Phone: 919-660-2513
  Duke University, Dept. of Physics       [EMAIL PROTECTED]
  Box 90305, Durham N.C. 27708-0305
--- spamd.raw.orig      Sun Nov 10 17:14:42 2002
+++ spamd.raw   Sun Nov 10 17:31:15 2002
@@ -54,7 +54,10 @@
                );
 
 # defaults
-my %opt = ('user-config' => 1);
+my %opt = (
+          'user-config' => 1,
+          'ident-timeout' => 5.0,
+         );
 
 my @OLD_ARGV = @ARGV;    # Getopt::Long tends to clear @ARGV
 Getopt::Long::Configure ("bundling");
@@ -82,6 +85,8 @@
        'paranoid!' => \$opt{'paranoid'}, 'P' => \$opt{'paranoid'},
        'stop-at-threshold!' => \$opt{'stop-at-threshold'}, 'S' => 
\$opt{'stop-at-threshold'},
        'helper-home-dir|H:s' => \$opt{'home_dir_for_helpers'},
+       'auth-ident' => \$opt{'auth-ident'},
+       'ident-timeout=f' => \$opt{'ident-timeout'},
 
         # will be stripped in future release
        'add-from!' => sub { warn "The --add-from option has been removed\n" },
@@ -102,6 +107,18 @@
     set_allowed_ip('127.0.0.1');
 }
 
+# ident-based spamc user authentication
+if ($opt{'auth-ident'}) {
+    eval { require Net::Ident };
+    if ($@) {
+       die "fatal: ident-based authentication requested, " .
+           "but Net::Ident is unavailable.\n";
+    } else {
+       $opt{'ident-timeout'} = undef if $opt{'ident-timeout'} >= 0.0;
+       import Net::Ident qw(ident_lookup);
+    }
+}
+
 # This can be changed on the command line with the -s flag
 my $log_facility = $opt{'syslog'} || 'mail';
 
@@ -389,6 +406,7 @@
            if (/^User: (.*)\r\n/)
            {
                $current_user = $1;
+               auth_ident($current_user) if $opt{'auth-ident'};
                if (!$opt{'user-config'})
                {
                  if ($opt{'sql-config'}) {
@@ -578,6 +596,19 @@
     exit &$coderef();
 }
 
+sub auth_ident
+{
+    my $username = shift;
+    my $ident_username = ident_lookup(\*STDIN, $opt{'ident-timeout'});
+    my $dn = $ident_username || 'NONE'; # display name
+    warn "ident_username = $dn, spamc_username = $username\n" if $opt{'debug'};
+    if ($username ne $ident_username) {
+       logmsg "fatal: ident username ($dn) does not match " .
+           "spamc username ($username)";
+       exit 1;
+    }
+}
+
 sub handle_user
 {
     my $username = shift;
@@ -867,6 +898,8 @@
  -u username, --username=username   Run as username
  -v, --vpopmail                     Enable vpopmail config
  -x, --nouser-config                Disable user config files
+ --auth-ident                       Use ident to authenticate spamc user
+ --ident-timeout=timeout            Timeout for ident connections
  -A host,..., --allowed-ips=..,..   Limit ip addresses which can connect
  -D, --debug                        Print debugging messages
  -L, --local                        Use local tests only (no DNS)
@@ -1002,6 +1035,24 @@
 Turn off(on) per-user config files.  All users will just get the default
 configuration.
 
+=item B<--auth-ident>
+
+Verify the username provided by spamc using ident.  This is only
+useful if connections are only allowed from trusted hosts (because an
+identd that lies is trivial to create) and if spamc REALLY SHOULD be
+running as the user it represents.  Connections are terminated
+immediately if authentication fails.  In this case, spamc will pass
+the mail through unchecked.  Failure to connect to an ident server,
+and response timeouts are considered authentication failures.  This
+requires that Net::Ident be installed.
+
+=item B<--ident-timeout>=I<timeout>
+
+Wait at most I<timeout> seconds for a response to ident queries.
+Authentication that takes long that I<timeout> seconds will fail, and
+mail will not be processed.  Setting this to 0.0 or less results in no
+timeout, which is STRONGLY discouraged.  The default is 5 seconds.
+
 =item B<-A> I<host,...>, B<--allowed-ips>=I<host,...>
 
 Specify a list of authorized hosts or networks which can connect to this spamd

Reply via email to