From 78cab525826cdca4367553b6fb5293e9ff2f04e2 Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Wed, 14 Nov 2012 23:21:20 -0500 Subject: [PATCH] SPF: use $conn->relay_client instead of duplicated is_in_relayclients method. Expects relay plugin to have set relay_client, a reasonable assumption. --- config.sample/relayclients | 10 +++++---- plugins/relay | 23 ++++++++++++++++----- plugins/sender_permitted_from | 39 ++--------------------------------- t/config.t | 2 +- 4 files changed, 27 insertions(+), 47 deletions(-) diff --git a/config.sample/relayclients b/config.sample/relayclients index a0fbc4e..31fcaeb 100644 --- a/config.sample/relayclients +++ b/config.sample/relayclients @@ -1,12 +1,14 @@ # used by plugins/relay -# Format is IP, or IP part with trailing dot +# IPv4 format is IP, or IP part with trailing dot # e.g. "127.0.0.1", or "192.168." 127.0.0.1 # leading/trailing whitespace is ignored 192.0. # -# IPv6 formats ends in a nibble (not a netmask, prefixlen, or colon) -# RFC 3849 example -2001:DB8 +# IPv6 formats can be compressed or expanded, may include a prefixlen, +# and can end on any nibble boundary. Nibble boundaries must be expressed +# in expanded format. (RFC 3849 example) +2001:0DB8 2001:DB8::1 +2001:DB8::1/32 2001:0DB8:0000:0000:0000:0000:0000:0001 diff --git a/plugins/relay b/plugins/relay index e8b0743..84658cf 100644 --- a/plugins/relay +++ b/plugins/relay @@ -37,12 +37,12 @@ Each line in I is one of: - partial IP address terminated by a dot or colon for matching whole networks 192.168.42. - fdda:b13d:e431:ae06: + 2001:db8:e431:ae06: ... - a network/mask, aka a CIDR block 10.1.0.0/24 - fdda:b13d:e431:ae06::/64 + 2001:db8:e431:ae06::/64 ... =head2 morerelayclients @@ -175,15 +175,20 @@ sub is_octet_match { my $self = shift; my $ip = $self->qp->connection->remote_ip; - $ip =~ s/::/:/; - if ( $ip eq ':1' ) { + if ( $ip eq '::1' ) { $self->log(LOGINFO, "pass, octet matched localhost ($ip)"); return 1; }; my $more_relay_clients = $self->qp->config('morerelayclients', 'map'); + my $ipv6 = $ip =~ /:/ ? 1 : 0; + + if ( $ipv6 && $ip =~ /::/ ) { # IPv6 compressed notation + $ip = Net::IP::ip_expand_address($ip,6); + }; + while ($ip) { if ( exists $self->{_octets}{$ip} ) { $self->log(LOGINFO, "pass, octet match in relayclients ($ip)"); @@ -194,7 +199,15 @@ sub is_octet_match { $self->log(LOGINFO, "pass, octet match in morerelayclients ($ip)"); return 1; }; - $ip =~ s/(\d|\w)+(:|\.)?$// or last; # strip off another 8 bits + + # added IPv6 support (Michael Holzt - 2012-11-14) + if ( $ipv6 ) { + $ip =~ s/[0-9a-f]:?$//; # strip off another nibble + chop $ip if ':' eq substr($ip, -1, 1); + } + else { + $ip =~ s/\d+\.?$// or last; # strip off another 8 bits + } } $self->log(LOGDEBUG, "no octet match" ); diff --git a/plugins/sender_permitted_from b/plugins/sender_permitted_from index 42f26d8..05044d8 100644 --- a/plugins/sender_permitted_from +++ b/plugins/sender_permitted_from @@ -59,8 +59,6 @@ use warnings; #use Mail::SPF 2.000; # eval'ed in ->register use Qpsmtpd::Constants; -use Net::IP; - sub register { my ($self, $qp, %args) = @_; eval 'use Mail::SPF'; @@ -92,8 +90,8 @@ sub mail_handler { return (DECLINED, "SPF - null sender"); }; - if ( $self->is_in_relayclients() ) { - $self->log( LOGINFO, "skip, in relayclients" ); + if ( $self->qp->connection->relay_client ) { + $self->log( LOGINFO, "skip, relay_client" ); return (DECLINED, "SPF - relaying permitted"); }; @@ -231,39 +229,6 @@ sub data_post_handler { return DECLINED; } -sub is_in_relayclients { - my $self = shift; - - my $client_ip = $self->qp->connection->remote_ip; - my @relay_clients = $self->qp->config('relayclients'); - my $more_relay_clients = $self->qp->config('morerelayclients', 'map'); - my %relay_clients = map { $_ => 1 } @relay_clients; - - my $ipv6 = $client_ip =~ /:/ ? 1 : 0; - - if ( $ipv6 && $client_ip =~ /::/ ) { # IPv6 compressed notation - $client_ip = Net::IP::ip_expand_address($client_ip,6); - }; - - while ($client_ip) { - if ( exists $relay_clients{$client_ip} || - exists $more_relay_clients->{$client_ip} ) { - $self->log( LOGDEBUG, "skip, IP in relayclients" ); - return 1; - }; - - # added IPv6 support (Michael Holzt - 2012-11-14) - if ( $ipv6 ) { - $client_ip =~ s/[0-9a-f]:*$//; # strip off another nibble - chop $client_ip if ':' eq substr($client_ip, -1, 1); - } - else { - $client_ip =~ s/\d+\.?$// or last; # strip off another 8 bits - } - } - return; -}; - sub is_special_recipient { my ($self, $rcpt) = @_; diff --git a/t/config.t b/t/config.t index 975e8d5..e82e185 100644 --- a/t/config.t +++ b/t/config.t @@ -26,7 +26,7 @@ is($smtpd->config('me'), 'some.host.example.org', 'config("me")'); # line with both) my $relayclients = join ",", sort $smtpd->config('relayclients'); is($relayclients, - '127.0.0.1,192.0.,2001:0DB8:0000:0000:0000:0000:0000:0001,2001:DB8,2001:DB8::1', + '127.0.0.1,192.0.,2001:0DB8:0000:0000:0000:0000:0000:0001,2001:DB8::1/32,2001:DB8,2001:DB8::1', 'config("relayclients") are trimmed'); foreach my $f ( @mes ) {