Why don't my LWP::UserAgent credentials work? - perl

I'm trying to access a protected file. Server is using digest authentication - which I can see from the printed out response.
Here is the sample code:
use LWP;
use strict;
my $url = 'http://somesite.com/aa/bb/cc.html';
my $username = 'scott';
my $password = 'tiger';
my $browser = LWP::UserAgent->new('Mozilla');
$browser->credentials("http://somesite.com:80","realm-name",$username=>$password);
my $response=$browser->get($url);
print $response->content;
Name of the realm I got it from the popup window I get when I try to access that resource from the browser. Same username and password are working extremely fine in the browser and I'm able to see the content but when I run the above script it always says 401 Authorization required.
How does LWP work?
Do I need to ask LWP to send MD5 hash (digest) of the username and password or is it like internally it checks which authentication to use and sends the corresponding (basic/digest) way of sending credentials.
My questions are
How can I set LWP so that it sends digest of username and password?
What if the server is using windows NTLM authentication protocol? How should I go about in such a situation?
any quick help is highly appreciated !

Consider the following excerpt from the LWP::UserAgent module's documentation:
$ua->credentials( $netloc, $realm )
$ua->credentials( $netloc, $realm, $uname, $pass )
Get/set the user name and password to be used for a realm.
The $netloc is a string of the form "<host>:<port>". The username and password will only be passed to this server. Example:
$ua->credentials("www.example.com:80", "Some Realm", "foo", "secret");
Change
$browser->credentials("http://somesite.com:80","realm-name",$username=>$password);
to
$browser->credentials("somesite.com:80","realm-name",$username=>$password);

HTTP GET Authed Request can also be done as follows
use LWP::UserAgent;
my $address = "localhost";
my $port = "8080";
my $username = "admin";
my $pass = "password";
my $browser = LWP::UserAgent->new;
my $req = HTTP::Request->new( GET => "http://$address:$port/path");
$req->authorization_basic( "$username", "$pass" );
my $page = $browser->request( $req );

When you have these sorts of issues, use an HTTP sniffer to watch the transaction so you can see the headers your program is sending. In this case, you're probably not sending the credentials at all since the HTTP status is 401 instead of 403. That usually means you've made a mistake with the credentials, as gbacon notes in his answer.

I solved this by installing perl-NTLM.noarch on Red Hat 7.

Related

How to implement https support for Perl's HTTP::DAV

I am trying to access a remote server via the WebDav protocol, and more specifically Perl's HTTP::DAV module.
According to its documentation the coupling to a remote directory takes place in the following manner:
use HTTP::DAV;
$d = HTTP::DAV->new();
$url = "http://host.org:8080/dav/";
$d->credentials(
-user => "pcollins",
-pass => "mypass",
-url => $url,
-realm => "DAV Realm"
);
$d->open( -url => $url )
or die("Couldn't open $url: " .$d->message . "\n");
I created a local webdav directory and can access it flawlessly over the http protocol.
According to HTTP::DAV's documentation, there should be and https support as well using the Crypt::SSLeay module.
The Crypt::SSLeay's documention offers us the following synopsys using inside the LWP::UserAgent module, thus providing for us web resource access over the https protocol:
use Net::SSL;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new(
ssl_opts => { verify_hostname => 0 },
);
my $response = $ua->get('https://www.example.com/');
print $response->content, "\n";
My question is:
How can I combine the HTTP::DAV and Crypt::SSLeay modules in order to have web resource access over the WebDav and https protocols?
Something like the following:
use HTTP::DAV;
$d = HTTP::DAV->new();
$url = "https://host.org:8080/dav/";
#...
This is untested, but from skimming the documentation, this should work:
$d->get_user_agent->ssl_opts( verify_hostname => 0 );
The documentation for HTTP::DAV says:
get_user_agent
Returns the clients' working HTTP::DAV::UserAgent object.
You may want to interact with the HTTP::DAV::UserAgent object to modify request headers or provide advanced authentication procedures.
HTTP::DAV::UserAgent isn't documented, but its source code shows it's a subclass of LWP::UserAgent. The documentation for LWP::UserAgent mentions the ssl_opts method for setting SSL options for the user agent object.

Can't connect to ... nodename nor servname provided, or not known

My question: why does my perl script--successful via home laptop--not work when run in the context of my hosting website? (Perhaps they have a firewall, for example. Perhaps my website needs to provide credentials. Perhaps this is in the realm of cross-site scripting. I DON'T KNOW and appeal for your help in my understanding what could be the cause and then the solution. Thanks!)
Note that all works fine IF I run the perl script from my laptop at home.
But if I upload the perl script to my web host, where I have a web page whose javascript successfully calls that perl script, there is an error back from the site whose URL is in the perl script (finance.yahoo in this example).
To bypass the javascript, I'm just typing the URL of my perl script, e.g. http://example.com/blah/script.pl
Here is the full error message from finance.yahoo when $url starts with http:
Can't connect to finance.yahoo.com:80 nodename nor servname provided, or not known at C:/Perl/lib/LWP/Protocol/http.pm line 47.
Here is the full error message from finance.yahoo when $url starts with https:
Can't connect to finance.yahoo.com:443 nodename nor servname provided, or not known at C:/Perl/lib/LWP/Protocol/http.pm line 47.
Code:
#!/usr/bin/perl
use strict; use warnings;
use LWP 6; # one site suggested loading this "for all important LWP classes"
use HTTP::Request;
### sample of interest: to scrape historical data and feed massaged facts to my private web page via js ajax
my $url = 'http://finance.yahoo.com/quote/sbux/profile?ltr=1';
my $browser = LWP::UserAgent->new;
# one site suggested having this empty cookie jar could help
$browser->cookie_jar({});
# another site suggested I should provide WAGuess
my #ns_headers = (
'User-Agent' =>
# 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0',
'Accept' => 'text/html, */*',
'Accept-Charset' => 'iso-8859-1,*,utf-8',
'Accept-Language' => 'en-US',
);
my $response = $browser->get($url, #ns_headers);
# for now, I just want to confirm, in my web page itself, that
# the target web page's contents was returned
my $content = $response->content;
# show such content in my web page
print "Content-type: text/html\n\n" . $content;
Well it is not obvious what is your final goal and it is possible that you over complicate the task.
You can retrieve above mentioned page with simpler perl code
#!/usr/bin/env perl
#
# vim: ai:ts=4:sw=4
#
use strict;
use warnings;
use feature 'say';
use HTTP::Tiny;
my $debug = 1;
my $url = 'https://finance.yahoo.com/quote/sbux/profile?ltr=1';
my $responce = HTTP::Tiny->new->get($url);
if ($responce->{success}) {
my $html = $responce->{content};
say $html if $debug;
}
In your post you indicated that javascript is somehow involved -- it is not clear how and what it's purpose in retrieving of the page.
Error message has a reference to at C:/Perl/lib/LWP/Protocol/http.pm line 47 which indicates that web hosting is taking place on Windows machine -- it would be nice to indicate it in your message.
Could you shed some light on purpose of following block in your code?
# WAGuess
$browser->env_proxy;
# WAGuess
$browser->cookie_jar({});
I do not see cookie_jar be utilized in your code anywhere.
Do you plan to use some authentication approach to extract some data under your personal account which is not accessible otherwise?
Please state in a few first sentences what you try to achieve on grand scale.
Perhaps it's about cookies or about using yahoo's "query" url instead.
Yahoo Finance URL not working

Certificates issue with a perl script

I need to use an url to connect with OSTR to create a ticket via webservice, but I have a problem with certificates.
The error (picture here):
500 Can't connect to (certificate verify failed)
What I've tried
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
my $UA = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0, } );
I've also tried to add a new certificate in C:\otrs\Kernel\cpan-lib\Mozilla\CA\cacert.pem.
CODE
Code (Picture here)
Well, please try this code and add/remove the line which sets the env variable, for me this just works.
use strict;
use warnings;
use SOAP::Lite;
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
my $URL = 'https://self-signed.badssl.com/foo';
my $NameSpace = 'https://self-signed.badssl.com/';
my $Operation = 'TicketCreate';
my $XMLData = <<'XML';
<UserLogin>login</UserLogin>
<Password>pass</Password>
<Ticket>
<Title>Title</Title>
</Ticket>
XML
my $SOAPObject = SOAP::Lite->uri($NameSpace)->proxy($URL)->$Operation($XMLData);
Without the $ENV{} line it gives 500 Can't connect ... (certificate verify failed) and with it it gives 405 Not Allowed (since the test URL does not actually run the SOAP web service).
Also, please place actual code snippets on SO, in text and not in a screenshot, and please try and keep them short.
Oh, and by the way, I wrote a small script to create tickets in OTRS using the web service, it's here, maybe it's useful for you -> https://github.com/mbeijen/App-OTRS-CreateTicket

S3 signature mismatch for presigned URL

I'm trying to create a pre signed URL for Amazon S3.
The below code generates the same signature as the signature in the example in the S3 docs.
(https://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html)
However, when I plug in my own credentials etc, I get an error from AWS:
"The request signature we calculated does not match the signature you provided. Check your key and signing method."
Given the code below seems to work, I presume my signing method is ok. Also, the credentials used are the ones
used to upload the file, so they are good too. They are root credentials, not an IAM user.
I have tried:
1) A file name with and without a period.
2) A file in US standard as well as Ireland.
3) HTTP and HTTPS
4) SHA256 (although this breaks the example in the docs.)
5) Different web clients: wget, curl and Firefox.
I seem to be doing exactly the same as the php given here:
Creating a signed S3 URL with Javascript
This is the URL generated for the US standard. Bucket is "buck1bar", file is "foo.txt"
https://s3.amazonaws.com/buck1bar/foo.txt?AWSAccessKeyId=AKIAJG5VR56AB5USIG5Q&Expires=1467893299&Signature=emdimX%2FWKYrcdhtPtE7eQ9ErWv30HNlAHaa9vlDODCY%3D
So, what am I doing wrong?
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use MIME::Base64;
use Digest::HMAC;
use Digest::SHA;
use URI::Escape;
my $hmac3 = Digest::HMAC->new( 'OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV', 'Digest::SHA');
$hmac3->add("GET\n\n\n1141889120\n/quotes/nelson");
my $signature = uri_escape( encode_base64 $hmac3->digest, '');
print "vjbyPxybdZaNmGa%2ByT272YEAiv4%3D\n$signature\n";
# vjbyPxybdZaNmGa%2ByT272YEAiv4%3D
# vjbyPxybdZaNmGa%2ByT272YEAiv4%3D
After further hackery, it turns out that the module I was using already does it.
my $client = Net::Amazon::S3::Client->new( s3 => $s3 );
my $bucket = $client->bucket( name => $bucket_name );
my $o = $bucket->object( key => 'key1', expires => '2016-07-08' );
my $uri = $o->query_string_authentication_uri();
print "$uri\n";

How can I connect to an HTTPS server using the Perl JIRA::Client::Automated module through Proxy?

I am new to use JIRA and REST API.Please tell me how to connect to HTTPS jira server using JIRA::Client::Automated module. I am trying to connect to jira server using below code.
use strict;
use warnings
use JIRA::Client::Automated;
my $user = 'foo';
my $pass = 'bar';
my $url = 'https://xxx.yyy';
my $jira = JIRA::Client::Automated->new($url, $user, $pass);
But using the above code always gives me an 500 error saying Unable to connect. Since I am trying to connect from my Local Machine, the request is not going through Local system proxy. Please let me know how to connect through Proxy.
Thanks for your Suggestion Daniel.
I have edited the code as per the your suggestion.
use strict;
use warnings
use JIRA::Client::Automated;
my $user = 'foo';
my $pass = 'bar';
my $url = 'https://xxx.yyy.com/jira-stage/';
my $jira = JIRA::Client::Automated->new($url, $user, $pass);
my $ua = $jira->ua();
$ua->proxy('http', 'http://proxy.com:8000');
$search_results = $jira->search_issues(project in (sample), 0, 1000);
my $count = $search_results->{'total'};
print "$count";
But still facing the same issue.Please suggest.
Look at the documentation of JIRA::Client::Automated. You can get the LWP::UserAgent object from it:
my $ua = $jira->ua;
Based on LWP::UserAgent's documentation you can set the proxy like this
$ua->proxy('https', 'https://proxy:8080/');
or make it load the proxy settings from respective environment variables this way:
$ua->env_proxy;