diff --git a/lib/Qpsmtpd.pm b/lib/Qpsmtpd.pm index 79a3623..be1cea4 100644 --- a/lib/Qpsmtpd.pm +++ b/lib/Qpsmtpd.pm @@ -591,7 +591,7 @@ sub spool_dir { unless ($Spool_dir) { # first time through $self->log(LOGDEBUG, "Initializing spool_dir"); $Spool_dir = $self->config('spool_dir') - || Qpsmtpd::Utils::tildeexp('~/tmp/'); + || Qpsmtpd::Utils->tildeexp('~/tmp/'); $Spool_dir .= "/" unless ($Spool_dir =~ m!/$!); diff --git a/lib/Qpsmtpd/Utils.pm b/lib/Qpsmtpd/Utils.pm index 38c2c6f..edd8d4e 100644 --- a/lib/Qpsmtpd/Utils.pm +++ b/lib/Qpsmtpd/Utils.pm @@ -2,13 +2,22 @@ package Qpsmtpd::Utils; use strict; sub tildeexp { - my $path = shift; + my ($self, $path) = @_; $path =~ s{^~([^/]*)} { - $1 + $1 ? (getpwnam($1))[7] : ( $ENV{HOME} || $ENV{LOGDIR} || (getpwuid($>))[7]) }ex; return $path; } +sub is_localhost { + my ($self, $ip) = @_; + return if ! $ip; + return 1 if $ip =~ /^127\./; # IPv4 + return 1 if $ip =~ /:127\./; # IPv4 mapped IPv6 + return 1 if $ip eq '::1'; # IPv6 + return; +} + 1; diff --git a/plugins/helo b/plugins/helo index b068672..d4e3a8c 100644 --- a/plugins/helo +++ b/plugins/helo @@ -340,13 +340,14 @@ sub is_regex_match { sub invalid_localhost { my ($self, $host) = @_; return if lc $host ne 'localhost'; - if ($self->qp->connection->remote_ip ne '127.0.0.1') { - - #$self->log( LOGINFO, "fail, not localhost" ); - return ("You are not localhost", "invalid localhost"); + my $ip = $self->qp->connection->remote_ip; + if ($ip && ($ip eq '127.0.0.1' || $ip eq '::1')) { + $self->log(LOGDEBUG, "pass, is localhost"); + return; } - $self->log(LOGDEBUG, "pass, is localhost"); - return; + + #$self->log( LOGINFO, "fail, not localhost" ); + return ("You are not localhost", "invalid localhost"); } sub is_plain_ip { diff --git a/t/plugin_tests/helo b/t/plugin_tests/helo index 25ba153..8790894 100644 --- a/t/plugin_tests/helo +++ b/t/plugin_tests/helo @@ -11,7 +11,7 @@ sub register_tests { $self->register_test('test_init_resolver', 2); $self->register_test('test_is_in_badhelo', 2); $self->register_test('test_is_regex_match', 3); - $self->register_test('test_invalid_localhost', 4); + $self->register_test('test_invalid_localhost', 5); $self->register_test('test_is_plain_ip', 3); $self->register_test('test_is_address_literal', 3); $self->register_test('test_no_forward_dns', 2); @@ -73,9 +73,11 @@ sub test_invalid_localhost { ($err, $why) = $self->invalid_localhost('localhost'); ok( $err, "localhost, invalid remote IP: $why"); - $self->qp->connection->remote_ip('127.0.0.1'); - ($err, $why) = $self->invalid_localhost('localhost'); - ok( ! $err, "localhost, correct remote IP"); + foreach my $ip (qw/ ::1 127.0.0.1 / ) { + $self->qp->connection->remote_ip($ip); + ($err, $why) = $self->invalid_localhost('localhost'); + ok( ! $err, "localhost, correct remote IP ($ip)"); + } }; sub test_is_plain_ip { diff --git a/t/qpsmtpd-utils.t b/t/qpsmtpd-utils.t new file mode 100644 index 0000000..0d278b9 --- /dev/null +++ b/t/qpsmtpd-utils.t @@ -0,0 +1,35 @@ +#!/usr/bin/perl +use strict; +use warnings; + +use Test::More; + +use lib 'lib'; # test lib/Qpsmtpd/Utils (vs site_perl) + +BEGIN { use_ok('Qpsmtpd::Utils'); } + +my $utils = bless {}, 'Qpsmtpd::Utils'; + +__tildeexp(); +__is_localhost(); + +done_testing(); + +sub __is_localhost { + + for my $local_ip (qw/ 127.0.0.1 ::1 2607:f060:b008:feed::127.0.0.1 127.0.0.2 /) { + ok( $utils->is_localhost($local_ip), "is_localhost, $local_ip"); + } + + for my $rem_ip (qw/ 128.0.0.1 ::2 2607:f060:b008:feed::128.0.0.1 /) { + ok( !$utils->is_localhost($rem_ip), "!is_localhost, $rem_ip"); + } +}; + +sub __tildeexp { + my $path = $utils->tildeexp('~root/foo.txt'); + ok( $path, "tildeexp, $path"); + + $path = $utils->tildeexp('no/tilde/in/path'); + cmp_ok( $path, 'eq', 'no/tilde/in/path', 'tildeexp, no expansion'); +};