Hi!

Scott Ryan wrote:
There is already an SPF patch for qmail-ldap and a plugin.
I was using it sometime ago.
Where is it? I know one about stock qmail, but not qmail-ldap.

On 5/30/07, *Zdravko Stoychev* < [EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>> wrote:

    Hi all! I have managed to run a perl script (called from .qmail or
    control/defaultdelivery) which performs SPF and DKIM checks on
    incoming
    messages. It is work in progress and needs some tuning as
    white-listing
    IP-nets is hardcoded (when sending from Intranet) and $dkim object
    usage, behavior on soft/hard-errors is hardcoded too, etc. Still it is
    working well on our ~150 mailboxes server so far. This is temporary
    solution for me until real qmail-src implementation is (probably)
    added
    for the SPF and/or DKIM RFCs. Feel free to enhance it and provide
    feedback.

    [attached: abusecheck.pl]

    --
      Zdravko Stoychev
      System Software and Support
      MPS Ltd.
      [EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>
      +359-2-491-1827 (ext.271)

    Not answered?
    http://6lyokavitza.org/mail

    PGP Public Key:
    http://keyserver.kjsl.com:11371/pks/lookup?op=get&search=0x2C64101C
    <http://keyserver.kjsl.com:11371/pks/lookup?op=get&search=0x2C64101C>

    Key Fingerprint:
    EC7E CA74 952D F343 2AAD 0F34 857D E27D 2C64 101C

    This e-mail is intended only for the addressee(s) and may contain
    privileged and confidential information. It should not be disse-
    minated, distributed, or copied. If you have received this e-mail
    message by mistake, please inform the sender, and delete it from
    your system.



    #!/usr/bin/perl
    #
    #       If you are using qmail as your MTA stick this file in the
    #       /var/qmail/bin/abusecheck.pl and chmod +x it, and then for
    #       each .qmail file which needs SPF/DKIM processing just add
    #
    #       |/var/qmail/bin/abusecheck.pl
    #
    #       to the top of the .qmail file -- normally before the Maildir
    #       line.
    #
    #       By default, this rejects nothing, but adds the Received-SPF
    #       or X-SPF-Guess header (for SPF), or Authentication-Results
    #       header (for DKIM). Rejecting is pretty useless as you know
    #       that the sender is forged!
    #
    #       Philip Gladstone - original SPF implementation
    #       Zdravko Stoychev - added DKIM implementation
    #

    use strict;

    use Sys::Hostname;
    use Mail::SPF::Query;
    use Mail::DKIM::Verifier;

    my $sender = $ENV{SENDER};
    my $src;
    my $helo;
    my $ourhost = hostname;

    my $softfail = 1;       # 0 = Don't delay ERROR messages,
                            # 1 = Delay SPF/DKIM msgs temporary

    my $hardfail = 1;       # 0 = Don't reject DENY messages,
                            # 1 = Reject SPF/DKIM FAIL messages

    if (exists $ENV{RELAYCLIENT}) {
        # This is a well-known allowed relaying client.
        # Signify that delivery is to continue
        exit 0;
    }

    my @msg;
    my $dkim = Mail::DKIM::Verifier->new();

    while (<>) {
        push @msg, $_;
        if (/^Received-SPF/i || /^X-SPF-Guess/i ||
    /^Authentication-Results/i) {
            # I tought to check that it is my record but since it appears
            # before the first received, it probably is mine.
            # Signify that delivery is to continue
            exit 0;
        }

        # remove local line terminators
        chomp;
        s/\015$//;
        # use SMTP line terminators
        $dkim->PRINT("$_\015\012");

        if (!$sender && /^Return-path: <(.*)>/i) {
            $sender = $1;
        }
        if (!$src && /^Received:\s*from\s+(\S+)\s.*\(\[([.\d]+)\]\)/i) {
            my $from = $1;
            $src = $2;
            ($helo) = /\(HELO (\S+)\)/;
            $helo ||= $from;
            last;
        }
    }

    if (!$src || $src =~ /^10\.0\./ || $src =~ /^192\.168\.0\./) {
        # This is probably a local delivery or sending from Intranet
        # Signify that delivery is to continue
        exit 0;
    }

    # OK, perform SPF check...
    my $spfheader = "Received-SPF"; # No spaces please!

    my $query = Mail::SPF::Query->new(ip => $src, sender => $sender,
    helo => $helo,
        guess => 1, trusted => 1, myhostname => $ourhost);

    my ($spfresult, $spferror, $spfcomment) = $query->result();

    if ($spfresult eq "fail") {
        # domain is forged!!!
        if ($hardfail) {
            print "SPF failed: $spferror";
            # Fail the delivery
            exit 100;
        }
    } elsif ($spfresult eq "error") {
        # DNS temporary error
        if ($softfail) {
            print $spferror;
            # Delay the delivery
            exit 111;
        }
    }

    $spfresult ||= 'unknown';

    my $spfoutput = "$spfresult";
    if ($spfcomment ne "") {
        $spfoutput = "$spfoutput ($spfcomment)";
    }

    # NEXT, perform DKIM check...
    while (<>) {
        push @msg, $_;
        # remove local line terminators
        chomp;
        s/\015$//;
        # use SMTP line terminators
        $dkim->PRINT("$_\015\012");
    }
    $dkim->CLOSE;

    # what is the result of the verify?
    my $dkimheader  = "Authentication-Results"; # No spaces please!
    my $dkimresult  = $dkim->result;
    my $dkimpolicy  = $dkim->fetch_author_policy;
    my $dkimcomment = $dkim->result_detail;

    if ($dkimresult eq "fail") {
        # domain is forged!!!
        if (! $dkimpolicy->testing && $hardfail) {
            print "DKIM failed: $dkimcomment";
            # Fail the delivery
            exit 100;
        }
    } elsif ($dkimresult eq "invalid") {
        # SIG temporary error
        if ($softfail) {
            print "DKIM signature: $dkimcomment";
            # Delay the delivery
            exit 111;
        }
    }

    $dkimresult ||= 'unknown';

    my $dkimwhy     = $dkimpolicy->apply($dkim);
    my $dkimoutput  = "$ourhost; mail.from=$sender; dkim=$dkimcomment;
    dkim.policy=$dkimwhy";
    if ($dkimpolicy->testing) {
        $dkimoutput = "$dkimoutput (testing)";
    }

    # Done
    ($ENV{QMAILSUSER}, $ENV{QMAILSHOST}) = $sender =~ /(.*)@([EMAIL 
PROTECTED])/;

    # Instead using LOCAL you might want to use RECIPIENT bellow,
    # depending of your qmail configuration
    open (MAIL, "|-") || exec 'qmail-inject', $ENV{LOCAL};

    # output checks results
    print MAIL "$dkimheader: $dkimoutput\n";
    print MAIL "$spfheader: $spfoutput\n";

    # output the message
    print MAIL @msg;
    # just in case
    #while (<>) { print MAIL; }
    close(MAIL) || exit 0;

    # Delivery OK, but don't continue in .qmail file
    exit 99;





--
slr

--
 Zdravko Stoychev
 System Software and Support
 MPS Ltd.
 [EMAIL PROTECTED]
 +359-2-491-1827 (ext.271)

Ако не отговарям на писмата Ви - погледнете тук: http://6lyokavitza.org/mail

--------------------------------------
"Quality is never an accident; it is always the result of high intention, sincere 
effort, intelligent direction, and skillful execution; it presents the wise choice of 
many alternatives."
- W. Foster.

--------------------------------------
This e-mail is intended only for the addressee(s) and may contain privileged 
and confidential information. It should not be disseminated, distributed, or 
copied. If you have received this e-mail message by mistake, please inform the 
sender, and delete it from your system.

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to