/[smeserver]/rpms/qpsmtpd/sme8/0014-rewrote-sender_permitted_from.patch
ViewVC logotype

Contents of /rpms/qpsmtpd/sme8/0014-rewrote-sender_permitted_from.patch

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (show annotations) (download)
Sun Nov 14 20:50:20 2010 UTC (13 years, 11 months ago) by slords
Branch: MAIN
CVS Tags: qpsmtpd-0_84-3_el5_sme, qpsmtpd-0_84-6_el5_sme, qpsmtpd-0_84-2_el5_sme, qpsmtpd-0_84-5_el5_sme, qpsmtpd-0_84-8_el5_sme, qpsmtpd-0_84-9_el5_sme, qpsmtpd-0_84-4_el5_sme, qpsmtpd-0_84-7_el5_sme, HEAD
* Sun Nov 14 2010 <slords@mail.com> 0.84-2.sme
- Sync with upstream git repo.
- Fix require_resolvable_fromhost doesn't work [SME: 6369]
- Fix TLS security defaults [SME: 6366]
- Fix fatal errors when mail has no headers [SME: 6345]

1 From 02912602842a5b2251b1455cf7206cfee3d18553 Mon Sep 17 00:00:00 2001
2 From: Matt Simerson <matt@tnpi.net>
3 Date: Tue, 11 May 2010 01:41:08 -0400
4 Subject: rewrote sender_permitted_from
5
6 rewrote the plugin using Mail::SPF, which is the replacement for Mail::SPF::Query (by the same author). The two plugins are mutually exclusive and SpamAssassin expects to have Mail::SPF available.
7
8 Signed-off-by: Robert <rspier@pobox.com>
9 ---
10 plugins/sender_permitted_from | 193 ++++++++++++++++++++++------------------
11 1 files changed, 106 insertions(+), 87 deletions(-)
12
13 diff --git a/plugins/sender_permitted_from b/plugins/sender_permitted_from
14 index 287847e..a6d833b 100644
15 --- a/plugins/sender_permitted_from
16 +++ b/plugins/sender_permitted_from
17 @@ -5,119 +5,138 @@ SPF - plugin to implement Sender Permitted From
18
19 =head1 SYNOPSIS
20
21 - # in config/plugins
22 - sender_permitted_from
23 +Prevents email sender address spoofing by checking the SPF policy of the purported senders domain.
24
25 -Or if you wish to issue 5xx on SPF fail:
26 +=head1 DESCRIPTION
27
28 - sender_permitted_from spf_deny 1
29 +Sender Policy Framework (SPF) is an e-mail validation system designed to prevent spam by addressing source address spoofing. SPF allows administrators to specify which hosts are allowed to send e-mail from a given domain by creating a specific SPF record in the public DNS. Mail exchangers then use the DNS to check that mail from a given domain is being sent by a host sanctioned by that domain's administrators. -- http://en.wikipedia.org/wiki/Sender_Policy_Framework
30 +
31 +=head1 CONFIGURATION
32
33 -Other arguments are 'trust 0' and 'guess 0'. These turn off processing of
34 -spf.trusted-forwarders.org and the best_guess functionality. It is unlikely
35 -that you want to turn these off.
36 +In config/plugins, add arguments to the sender_permitted_from line.
37
38 -Adding 'spf_deny 2' will also issue a 5xx on a softfail response.
39 + sender_permitted_from spf_deny 1
40
41 -You can also specify local SPF policy with
42 +=head2 spf_deny
43
44 - include '<spf mechanism list>'
45 +Setting spf_deny to 0 will prevent emails from being rejected, even if they fail SPF checks. sfp_deny 1 is the default, and a reasonable setting. It temporarily defers connections (4xx) that have soft SFP failures and only rejects (5xx) messages when the sending domains policy suggests it. Settings spf_deny to 2 is more aggressive and will cause soft failures to be rejected permanently.
46
47 See also http://spf.pobox.com/
48
49 +=head1 AUTHOR
50 +
51 +Matt Simerson <msimerson@cpan.org>
52 +
53 +=head1 ACKNOWLEDGEMENTS
54 +
55 +whomever wrote the original SPF plugin, upon which I based this.
56 +
57 =cut
58
59 -use Mail::SPF::Query 1.991;
60 +use strict;
61 +use Mail::SPF 2.000;
62 +use Data::Dumper;
63
64 sub register {
65 - my ($self, $qp, @args) = @_;
66 - %{$self->{_args}} = @args;
67 + my ($self, $qp, @args) = @_;
68 + %{$self->{_args}} = @args;
69 }
70
71 sub hook_mail {
72 - my ($self, $transaction, $sender, %param) = @_;
73 -
74 - return (DECLINED) unless ($sender->format ne "<>"
75 - and $sender->host && $sender->user);
76 -
77 - # If we are receving from a relay permitted host, then we are probably
78 - # not the delivery system, and so we shouldn't check
79 -
80 - return (DECLINED) if $self->qp->connection->relay_client();
81 - my @relay_clients = $self->qp->config("relayclients");
82 - my $more_relay_clients = $self->qp->config("morerelayclients", "map");
83 - my %relay_clients = map { $_ => 1 } @relay_clients;
84 - my $client_ip = $self->qp->connection->remote_ip;
85 - while ($client_ip) {
86 - return (DECLINED) if exists $relay_clients{$client_ip};
87 - return (DECLINED) if exists $more_relay_clients->{$client_ip};
88 - $client_ip =~ s/\d+\.?$//; # strip off another 8 bits
89 - }
90 -
91 - my $host = lc $sender->host;
92 - my $from = $sender->user . '@' . $host;
93 -
94 - my $ip = $self->qp->connection->remote_ip;
95 - my $helo = $self->qp->connection->hello_host;
96 -
97 - my $query = Mail::SPF::Query->new(ip => $ip, sender => $from, helo => $helo,
98 - sanitize => 1,
99 - local => $self->{_args}{local},
100 - guess => defined($self->{_args}{guess}) ? $self->{_args}{guess} : 1,
101 - trusted => defined($self->{_args}{trust}) ? $self->{_args}{trust} : 1)
102 - || die "Couldn't construct Mail::SPF::Query object";
103 - $transaction->notes('spfquery', $query);
104 -
105 - return (DECLINED);
106 + my ($self, $transaction, $sender, %param) = @_;
107 +
108 + my $format = $sender->format;
109 + my $host = lc $sender->host;
110 + my $user = $sender->user;
111 + my $client_ip = $self->qp->connection->remote_ip;
112 + my $from = $sender->user . '@' . $host;
113 + my $helo = $self->qp->connection->hello_host;
114 +
115 + return (DECLINED, "SPF - null sender")
116 + unless ($format ne "<>" && $host && $user);
117 +
118 + # If we are receving from a relay permitted host, then we are probably
119 + # not the delivery system, and so we shouldn't check
120 + return (DECLINED, "SPF - relaying permitted")
121 + if $self->qp->connection->relay_client();
122 +
123 + my @relay_clients = $self->qp->config("relayclients");
124 + my $more_relay_clients = $self->qp->config("morerelayclients", "map");
125 + my %relay_clients = map { $_ => 1 } @relay_clients;
126 + while ($client_ip) {
127 + return (DECLINED, "SPF - relaying permitted")
128 + if exists $relay_clients{$client_ip};
129 + return (DECLINED, "SPF - relaying permitted")
130 + if exists $more_relay_clients->{$client_ip};
131 + $client_ip =~ s/\d+\.?$//; # strip off another 8 bits
132 + }
133 +
134 + my $scope = $from ? 'mfrom' : 'helo';
135 + $client_ip = $self->qp->connection->remote_ip;
136 + my %req_params = (
137 + versions => [1, 2], # optional
138 + scope => $scope,
139 + ip_address => $client_ip,
140 + );
141 +
142 + if ($scope =~ /mfrom|pra/) {
143 + $req_params{identity} = $from;
144 + $req_params{helo_identity} = $helo if $helo;
145 + }
146 + elsif ($scope eq 'helo') {
147 + $req_params{identity} = $helo;
148 + $req_params{helo_identity} = $helo;
149 + }
150 +
151 + my $spf_server = Mail::SPF::Server->new();
152 + my $request = Mail::SPF::Request->new(%req_params);
153 + my $result = $spf_server->process($request);
154 +
155 + $transaction->notes('spfquery', $result);
156 +
157 + return (OK) if $result->code eq 'pass'; # this test passed
158 + return (DECLINED, "SPF - $result->code");
159 }
160
161 sub hook_rcpt {
162 - my ($self, $transaction, $rcpt, %param) = @_;
163 -
164 - # special addresses don't get SPF-tested.
165 - return DECLINED if $rcpt and $rcpt->user and $rcpt->user =~ /^(?:postmaster|abuse|mailer-daemon|root)$/i;
166 -
167 - my $query = $transaction->notes('spfquery');
168 -
169 - return DECLINED if !$query;
170 - my ($result, $smtp_comment, $comment) = $query->result2($rcpt->address);
171 -
172 - if ($result eq "error") {
173 - return (DENYSOFT, "SPF error: $smtp_comment");
174 - }
175 -
176 - if ($result eq "fail" and $self->{_args}{spf_deny}) {
177 - return (DENY, "SPF forgery: $smtp_comment");
178 - }
179 -
180 - if ($result eq "softfail" and $self->{_args}{spf_deny} > 1) {
181 - return (DENY, "SPF probable forgery: $smtp_comment");
182 - }
183 -
184 - if ($result eq 'fail' or $result eq 'softfail') {
185 - $self->log(LOGDEBUG, "result for $rcpt->address was $result: $comment");
186 - }
187 -
188 - return DECLINED;
189 -}
190 + my ($self, $transaction, $rcpt, %param) = @_;
191 +
192 + # special addresses don't get SPF-tested.
193 + return DECLINED
194 + if $rcpt
195 + and $rcpt->user
196 + and $rcpt->user =~ /^(?:postmaster|abuse|mailer-daemon|root)$/i;
197 +
198 + my $result = $transaction->notes('spfquery') or return DECLINED;
199 + my $code = $result->code;
200 + my $why = $result->local_explanation;
201 + my $deny = $self->{_args}{spf_deny};
202 +
203 + return (DECLINED, "SPF - $code: $why") if $code eq "pass";
204 + return (DECLINED, "SPF - $code, $why") if !$deny;
205 + return (DENYSOFT, "SPF - $code: $why") if $code eq "error";
206 + return (DENY, "SPF - forgery: $why") if $code eq 'fail';
207
208 -sub _uri_escape {
209 - my $str = shift;
210 - $str =~ s/([^A-Za-z0-9\-_.!~*\'()])/sprintf "%%%X", ord($1)/eg;
211 - return $str;
212 + if ($code eq "softfail") {
213 + return (DENY, "SPF probable forgery: $why") if $deny > 1;
214 + return (DENYSOFT, "SPF probable forgery: $why");
215 + }
216 +
217 + $self->log(LOGDEBUG, "result for $rcpt->address was $code: $why");
218 +
219 + return (DECLINED, "SPF - $code, $why");
220 }
221
222 sub hook_data_post {
223 - my ($self, $transaction) = @_;
224 -
225 - my $query = $transaction->notes('spfquery');
226 - return DECLINED if !$query;
227 + my ($self, $transaction) = @_;
228
229 - my ($result, $smtp_comment, $comment) = $query->message_result2();
230 + my $result = $transaction->notes('spfquery') or return DECLINED;
231
232 - $self->log(LOGDEBUG, "result was $result: $comment") if ($result);
233 + $self->log(LOGDEBUG, "result was $result->code");
234
235 - $transaction->header->add('Received-SPF' => "$result ($comment)", 0);
236 + $transaction->header->add('Received-SPF' => $result->received_spf_header,
237 + 0);
238
239 - return DECLINED;
240 + return DECLINED;
241 }
242
243 --
244 1.7.2.2
245

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed