Subject: | surplus wrong Basic Authentication header in LWP::Protocol::http10.pm |
Symptom: Using libwww-perl with apache modperl, our http request was rejected by some server because there is always a un-removable header: "Authentication: Basic Lzo=", while we never set any authentication anywhere.
Version of libwww-perl: from latest version 5.69, back to at least 5.64.
Directly looking into the source code can shorten the story.
In libwww-perl-5.69/lib/LWP/Protocol/http10.pm, sub _fixup_header(),
original code is like:
----------------------------
$hhost =~ s/^([^\@]*)\@//;
if (defined($1)) {
...
}
----------------------------
This is evidently should be rewrite as:
----------------------------
if ($hhost =~ s/^([^\@]*)\@//) {
...
}
----------------------------
Because any previous matching result in $1 will ever lasting, I think
this is a trivial mistake. For who want to understand the problem, I
still give here a snippet:
----------------------------
#!/usr/bin/perl
my $dummy = 'tom:secret@www.geocity.org';
$dummy =~ s/^([^\@]*)\@//;
my $hhost = "www.asahi-net.co.jp";
$hhost =~ s/^([^\@]*)\@//;
if (defined($1)) {
print "user:password on $hhost is $1\n";
}
1;
----------------------------
The print result will tell you that "tom:secret" is also
the user:password on "asahi-net".
For some people, this might be a irrelevant problem. For people using
libwww-perl, accessing user assigned web site, this may cause a serious
trouble. Server never give you which you expected, just like from browser.
Finally, there is also a same problem in
libwww-perl-5.69/lib/LWP/Protocol/http.pm, should be fixed as above.
--- http10.pm.org Sat Oct 27 02:27:19 2001
+++ http10.pm Tue Jan 28 10:42:45 2003
@@ -67,17 +67,18 @@
# HTTP/1.1 will require us to send the 'Host' header, so we might
# as well start now.
my $hhost = $url->authority;
- $hhost =~ s/^([^\@]*)\@//; # get rid of potential "user:pass@"
- $h->header('Host' => $hhost) unless defined $h->header('Host');
- # add authorization header if we need them. HTTP URLs do
- # not really support specification of user and password, but
- # we allow it.
- if (defined($1) && not $h->header('Authorization')) {
- require URI::Escape;
- $h->authorization_basic(map URI::Escape::uri_unescape($_),
+ if ($hhost =~ s/^([^\@]*)\@//) { # get rid of potential "user:pass@"
+ # add authorization header if we need them. HTTP URLs do
+ # not really support specification of user and password, but
+ # we allow it.
+ if (not $h->header('Authorization')) {
+ require URI::Escape;
+ $h->authorization_basic(map URI::Escape::uri_unescape($_),
split(":", $1, 2));
+ }
}
+ $h->header('Host' => $hhost) unless defined $h->header('Host');
if ($proxy) {
# Check the proxy URI's userinfo() for proxy credentials