spf-discuss
[Top] [All Lists]

Re: Starting spfd (FreeBSD)

2003-12-17 17:01:43
Meng Weng Wong wrote:
Could somebody please post the latest spfd in its entirety?  It might
actually be shorter than the patches.  thanks.

This spfd includes Jonathan and my patches.

--
=> Mark Foster <mark(_at_)foster(_dot_)cc>     http://mark.foster.cc/

-------
Sender Permitted From: http://spf.pobox.com/
Archives at http://archives.listbox.com/spf-discuss/current/
Latest draft at http://spf.pobox.com/draft-mengwong-spf-02.9.4.txt
To unsubscribe, change your address, or temporarily deactivate your subscription, please go to http://v2.listbox.com/member/?listname(_at_)©#«Mo\¯HÝÜîU;±¤Ö¤Íµø?¡
#!/usr/local/bin/perl -sw

eval 'exec /usr/local/bin/perl -sw -S $0 ${1+"$@"}'
    if 0; # not running under some shell

# simple forking daemon to provide SPF services
# mengwong+spf(_at_)pobox(_dot_)com
# Tue Oct 28 00:46:44 EST 2003
# 
# echo "ip=IP\nhelo=HELOHOST\nsender=EMAILADDRESS\n" | nc localhost 5970
#
# or use Mail::Postfix::Attr to query spfd over a unix domain socket.
#
# ./spfd -port=5970             # inet socket
# ./spfd -path=/var/spfd        # unix domain socket
# [-user=(uid|username)]        #setuid user for process if using inet socket
#                               # or chown if using unix-socket         
# [-group=(gid|groupname)]      # as above, but with group

use Mail::SPF::Query;
use Socket;

use strict;
use vars qw($port $path $group $user);

sub usage () {
  print "usage: spfd ( -port=5970 | -path=/var/spfd ) [-user=(uid|username)] 
[-group=(gid|groupname)]\n";
  print "usage: spfd assuming -port=5970\n";
}

sub DEBUG () { $ENV{DEBUG} }

if (not $port and not $path) {
  usage;
  $port=5970;
}

if ($port and $path) {
  usage;
  exit 1;
}

if ($group =~ /\D/) {
  $group = getgrnam($group) || die "Group: $group not found\n";
}

if ($port and $group) {
  $( = $) = $group;
  unless ($( == $) and $( == $group) {
    die( "setgid($group) call failed: $!\n" );
  }
}

if ($user =~ /\D/) {
  $user = getpwnam($user) || die "User: $user not found\n"; 
}

if ($port and $user) {
   $< = $> = $user;
   unless ($< == $> and $< == $user) {
    die( "setuid($user) call failed: $!\n" );
  }
}

$|++;

my @args;
my $sock_type;

if ($port) {
  $sock_type = "inet";
  @args = (Listen    => 1,
           LocalAddr => "127.0.0.1",
           LocalPort => $port,
           ReuseAddr => 1
           );
  print "$$ will listen on $port\n";
  $0 = "spfd listening on $port";
} elsif ($path) {
  $sock_type = "unix";
  unlink $path if -S $path;
  @args = (Listen => 1,
           Local => $path,
           );
  print "$$ will listen at $path\n";
  $0 = "spfd listening at $path";
}

print "$$: creating server with args @args\n";

my $server = $sock_type eq "inet" ? IO::Socket::INET->new(@args) : 
IO::Socket::UNIX->new(@args);
if ($path) {
        if ($group and $user) {
                chown $user, $group, $path or die "Cannot chown $user, $group 
on $path -- $!";

        } elsif ($user) {
                chown $user, -1, $path or die "Cannot chown $user on $path -- 
$!";
        }
        # fixup perms so that our user/group can read/write to the unix socket
        chmod 0660, $path or die "Cannot fixup perms on $path -- $!";
}
DEBUG and print "$$: server is $server\n";

while (my $sock = $server->accept()) {
  if    (fork) { close $sock; wait; next; } # this is the grandfather trick.
  elsif (fork) {                    exit; } # the child exits immediately, so 
no zombies.

  my $oldfh = select($sock); $| = 1; select($oldfh);

  my %in;

  while (<$sock>) {
    chomp; chomp;
    last if (/^$/);
    my ($lhs, $rhs) = split /=/, $_, 2;
    $in{lc $lhs} = $rhs;
  }

  my $peerinfo = $sock_type eq "inet" ? ($sock->peerhost . "/" . 
gethostbyaddr($sock->peeraddr, AF_INET)) : "";

  my $time = localtime;
  
  DEBUG and print "$time $peerinfo\n";
  foreach my $key (sort keys %in) { DEBUG and print "learned $key = 
$in{$key}\n" };

  my %q = map { exists $in{$_} ? ($_ => $in{$_}) : () } qw ( ip ipv4 ipv6 
sender helo fallbacks guess_mechs );

  my %a;

  my $query = eval { Mail::SPF::Query->new(%q); };

  my $error = $@; for ($error) { s/\n/ /; s/\s+$//; }

  if ($@) { @a{qw(result smtp_comment header_comment)} = ("unknown", $error, 
"SPF error: $error"); }
  else {
    @a{qw(result smtp_comment header_comment)} = $query->result();
    @a{qw(guess  smtp_guess   header_guess  )} = $query->best_guess();
  }

  if (DEBUG) {
    for (qw(result smtp_comment header_comment
          guess  smtp_guess   header_guess)) {
      print "moo!  $_=$a{$_}\n";
    }
  }

  for (qw(result smtp_comment header_comment
          guess  smtp_guess   header_guess)) {
    no warnings 'uninitialized';
    print $sock "$_=$a{$_}\n";
  }

  DEBUG and print "moo!  output all done.\n";
  print $sock "\n";
  DEBUG and print "\n";

  close $sock;

  exit;
}

-------
Sender Permitted From: http://spf.pobox.com/
Archives at http://archives.listbox.com/spf-discuss/current/
Latest draft at http://spf.pobox.com/draft-mengwong-spf-02.9.4.txt
To unsubscribe, change your address, or temporarily deactivate your 
subscription, 
please go to 
http://v2.listbox.com/member/?listname(_at_)©#«Mo\¯HÝÜîU;±¤Ö¤Íµø?¡
<Prev in Thread] Current Thread [Next in Thread>