Skip Menu |

This queue is for tickets about the libnet CPAN distribution.

Report information
The Basics
Id: 100235
Status: open
Priority: 0/
Queue: libnet

People
Owner: Nobody in particular
Requestors: nine [...] detonation.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 3.02
Fixed in: (no value)



Subject: Infinite loop in Net::SMTP::auth with Authen::SASL::XS installed
I'm trying to use Net::SMTP to connect to an SMTP server that requires authentication to send email. With Authen::SASL::XS (1.00) installed, Net::SMTP::auth falls into an endless loop trying to find a working auth mechanism. $str = $client->client_start; (line 203) returns undef. $client->error returns: "invalid parameter suppliedSASL(-7): invalid parameter supplied: Parameter error in client.c near line 709client_start error. (Callbacks?)" $client is now set but $client->mechanism returns undef. Therefore $mechanisms =~ s/\b\Q$failed_mechanism\E\b//; does not change $mechanisms at all and the loop tries the same $mechanisms over and over again. Uninstalling Authen::SASL::XS is as a workaround for us since with Authen::SASL::Perl everything seems to work just fine.
On Mon Nov 10 08:10:12 2014, NINE wrote: Show quoted text
> I'm trying to use Net::SMTP to connect to an SMTP server that requires > authentication to send email. With Authen::SASL::XS (1.00) installed, > Net::SMTP::auth falls into an endless loop trying to find a working > auth mechanism. $str = $client->client_start; (line 203) > returns undef. $client->error returns: "invalid parameter > suppliedSASL(-7): invalid parameter supplied: Parameter error in > client.c near line 709client_start error. (Callbacks?)" > > $client is now set but $client->mechanism returns undef. Therefore > $mechanisms =~ s/\b\Q$failed_mechanism\E\b//; does not change > $mechanisms at all and the loop tries the same $mechanisms over and > over again. > > Uninstalling Authen::SASL::XS is as a workaround for us since with > Authen::SASL::Perl everything seems to work just fine.
Thanks for the report. What happens if you insert "last unless $failed_mechanism =~ /\S/;" after "my $failed_mechanism = $client->mechanism;", like this: if ($client) { # $client mechanism failed, so we need to exclude this mechanism from list my $failed_mechanism = $client->mechanism; last unless $failed_mechanism =~ /\S/; $self->debug_text("Auth mechanism failed: $failed_mechanism") if $self->debug; $mechanisms =~ s/\b\Q$failed_mechanism\E\b//; last unless $mechanisms =~ /\S/; $sasl->mechanism($mechanisms); } Presumably that will fix the infinite loop, but the authentication will fail?
Another question: Is your Authen::SASL::XS linked with SASLv1 (LIBS="-lsasl") or SASLv2 (LIBS="-lsasl2" DEFINE="-DSASL2")? I suspect the problem lies in the Authen::SASL::XS distribution. That it works with Authen::SASL::Perl suggests that the libnet end of things is OK. I could change libnet to explicitly use ::Perl rather than ::XS, which would presumably fix your problem, but it doesn't seem very nice. Maybe necessary, though, if ::XS has a problem that libnet can't work around... It would be worth knowing which SASL library version was used, though: Maybe the problem is only with v1, in which case libnet could possibly check for v2 support, and otherwise use ::Perl...
Show quoted text
> Presumably that will fix the infinite loop, but the authentication will fail?
Yes. It fails with: Net::SMTP=GLOB(0x1e78330)>>> AUTH Net::SMTP=GLOB(0x1e78330)<<< 501 5.5.4 Syntax: AUTH mechanism Btw. I had to use goto with a label added after the loop because "last" doesn't work with do {} blocks. Show quoted text
> Another question: Is your Authen::SASL::XS linked with SASLv1 (LIBS="-lsasl") or SASLv2 (LIBS="-lsasl2" DEFINE="-DSASL2")?
Looks like SASLv2: cc -c -I/usr/local/include -D_REENTRANT -D_GNU_SOURCE -DPERL_USE_SAFE_PUTENV -fwrapv -fno-strict-aliasing -pipe -fstack-protector -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -Wall -pipe -DVERSION=\"1.00\" -DXS_VERSION=\"1.00\" -fPIC "-I/usr/lib/perl5/5.20.1/x86_64-linux-thread-multi/CORE" -DSASL2 XS.c The installes SASL package is cyrus-sasl-2.1.26-7.2.1.x86_64
On Sun Dec 07 05:34:56 2014, NINE wrote: Show quoted text
> > Presumably that will fix the infinite loop, but the authentication > > will fail?
> > Yes. It fails with: > Net::SMTP=GLOB(0x1e78330)>>> > AUTH > Net::SMTP=GLOB(0x1e78330)<<< 501 5.5.4 Syntax: AUTH mechanism > > Btw. I had to use goto with a label added after the loop because > "last" doesn't work with do {} blocks.
Thanks, and for the heads-up on the erroneous use of "last". There is actually no point in continuing auth() if the failed mechanism isn't known (since there is no way of removing it from the list to continue trying with), or if there are no more mechanisms left to try with -- either way it will just end up sending an "AUTH" command with no arguments, which is a syntax error (as reported above). So we may as well just return early in these cases. Hopefully the following should now fix the infinite loop problem: my $client; my $str; do { if ($client) { # $client mechanism failed, so we need to exclude this mechanism from list my $failed_mechanism = $client->mechanism; return unless defined $failed_mechanisms; $self->debug_text("Auth mechanism failed: $failed_mechanism") if $self->debug; $mechanisms =~ s/\b\Q$failed_mechanism\E\b//; return unless $mechanisms =~ /\S/; $sasl->mechanism($mechanisms); } # We should probably allow the user to pass the host, but I don't # currently know and SASL mechanisms that are used by smtp that need it $client = $sasl->client_new('smtp', ${*$self}{'net_smtp_host'}, 0); $str = $client->client_start; } while (!defined $str); Show quoted text
>
> > Another question: Is your Authen::SASL::XS linked with SASLv1 > > (LIBS="-lsasl") or SASLv2 (LIBS="-lsasl2" DEFINE="-DSASL2")?
> > Looks like SASLv2: > > cc -c -I/usr/local/include -D_REENTRANT -D_GNU_SOURCE > -DPERL_USE_SAFE_PUTENV -fwrapv -fno-strict-aliasing -pipe -fstack- > protector -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fmessage- > length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack- > protector -funwind-tables -fasynchronous-unwind-tables -g -Wall -pipe > -DVERSION=\"1.00\" -DXS_VERSION=\"1.00\" -fPIC "- > I/usr/lib/perl5/5.20.1/x86_64-linux-thread-multi/CORE" -DSASL2 XS.c > > The installes SASL package is cyrus-sasl-2.1.26-7.2.1.x86_64
Ok, so it's no use trying to required only SASLv2 then :-/ I will try to chase up why Authen::SASL::XS is not working correctly, but if I can't get to the bottom of it then I'll probably just end up using Authen::SASL::Perl instead (at least for now).
On Mon Dec 08 09:03:11 2014, SHAY wrote: Show quoted text
> So we may as well just return early in these cases. Hopefully the > following should now fix the infinite loop problem: > > my $client; > my $str; > do { > if ($client) { > # $client mechanism failed, so we need to exclude this mechanism > from list > my $failed_mechanism = $client->mechanism; > return unless defined $failed_mechanisms; > $self->debug_text("Auth mechanism failed: $failed_mechanism") > if $self->debug; > $mechanisms =~ s/\b\Q$failed_mechanism\E\b//; > return unless $mechanisms =~ /\S/; > $sasl->mechanism($mechanisms); > } > > # We should probably allow the user to pass the host, but I don't > # currently know and SASL mechanisms that are used by smtp that need > it > > $client = $sasl->client_new('smtp', ${*$self}{'net_smtp_host'}, 0); > $str = $client->client_start; > } while (!defined $str);
This is now done in https://github.com/steve-m-hay/perl-libnet/commit/56e5ec7a786f0a0b5c95f017285b8b9791de068a Show quoted text
> > > >
> >
> > > Another question: Is your Authen::SASL::XS linked with SASLv1 > > > (LIBS="-lsasl") or SASLv2 (LIBS="-lsasl2" DEFINE="-DSASL2")?
> > > > Looks like SASLv2: > > > > cc -c -I/usr/local/include -D_REENTRANT -D_GNU_SOURCE > > -DPERL_USE_SAFE_PUTENV -fwrapv -fno-strict-aliasing -pipe -fstack- > > protector -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -fmessage- > > length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack- > > protector -funwind-tables -fasynchronous-unwind-tables -g -Wall -pipe > > -DVERSION=\"1.00\" -DXS_VERSION=\"1.00\" -fPIC "- > > I/usr/lib/perl5/5.20.1/x86_64-linux-thread-multi/CORE" -DSASL2 XS.c > > > > The installes SASL package is cyrus-sasl-2.1.26-7.2.1.x86_64
> > Ok, so it's no use trying to required only SASLv2 then :-/ > > I will try to chase up why Authen::SASL::XS is not working correctly, > but if I can't get to the bottom of it then I'll probably just end up > using Authen::SASL::Perl instead (at least for now).
I have logged a ticket on the Authen::SASL queue about this: https://rt.cpan.org/Ticket/Display.html?id=100801