PERL Get_Server_Certificate certificate verify failed error - perl

I'm receiving a certificate error when trying to send a POST message to a website.
The error I'm receiving:
LWP::Protocol::https::Socket: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed at /usr/lib/perl5/site_perl/5.8.8/LWP/Protocol/http.pm line 49
The code that I'm using is:
my $webpage = "";
my $ua = LWP::UserAgent->new( );
$ua->agent('Mozilla');
$webpage = "https://mysite:444/myapp/app.aspx";
my $msg = 'An XML Message';
my $req = POST $webpage,
Content_Type => 'text/xml',
Content => $msg;
So far I've tried a few "fixes" that I've found online:
Tried disabling verify hostname through environment variable:
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0;
Tried disabling verify hostname through ssl_opts:
my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 }, );
Tried using the Mozilla CA and setting HTTPS_CA_FILE to /usr/lib/perl5/site_perl/5.8.8/Mozilla/CA/cacert.pem?
At this point I'm out of options to try so I'm hoping someone has run into this problem before and can provide assistance.

It's just a typo, use "verify_hostname" without the "s":
my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 }, );

Related

I can't connect using an api

I'm quite new to API's so I don't know if this should be more straight forward.
I write the following perl script
use strict;
use LWP::UserAgent;
require HTTP::Request;
my $request = HTTP::Request->new(GET => 'http://api.elsevier.com/content/ev/results?apiKey=1234&query=stress&database=c&updateNumber=1&pageSize=1');
my $ua = LWP::UserAgent->new;
my $response = $ua->request($request);
then when I get my response and print it in the debugger I get the following
HTTP::Response=HASH(0x9aedff8)
'_content' => '{"service-error":{"status":{"statusCode":"AUTHENTICATION_ERROR","statusText":"Requestor configuration settings insufficient for access to this resource."}}}'
'_headers' => HTTP::Headers=HASH(0x9aedfe8)
'allow' => 'GET'
'client-date' => 'Wed, 29 Mar 2017 08:08:25 GMT'
'client-peer' => '198.185.19.118:80'
'client-response-num' => 1
'content-length' => 156
'content-type' => 'application/json;charset=UTF-8'
'date' => 'Wed, 29 Mar 2017 08:08:24 GMT'
'p3p' => 'CP="IDC DSP LAW ADM DEV TAI PSA PSD IVA IVD CON HIS TEL OUR DEL SAM OTR IND OTC"'
'server' => 'api.elsevier.com 9999'
'vary' => 'Origin'
'x-cnection' => 'close'
'x-els-apikey' => 'e688c9db4db0386581dbe4c4dda46164'
'x-els-reqid' => '0000015b190d89fe-a0d0'
'x-els-status' => 'AUTHENTICATION_ERROR(Requestor configuration settings insufficient for access to this resource.)'
'x-els-transid' => 'cbf787b4-d171-4e35-8237-8cab3c931205'
'x-re-ref' => '1 1490774904423414'
'_msg' => 'Forbidden'
'_protocol' => 'HTTP/1.1'
'_rc' => 403
'_request' => HTTP::Request=HASH(0x9fc3000)
'_content' => ''
'_headers' => HTTP::Headers=HASH(0x9ae73e0)
'user-agent' => 'libwww-perl/5.831'
'_method' => 'GET'
'_uri' => URI::http=SCALAR(0x9e25188)
-> 'http://api.elsevier.com/content/ev/results?apiKey=e688c9db4db0386581dbe4c4dda46164&query=stress&database=c&updateNumber=1&pageSize=1'
'_uri_canonical' => URI::http=SCALAR(0x9e25188)
-> REUSED_ADDRESS
one of the notable lines is
x-els-status' => 'AUTHENTICATION_ERROR(Requestor configuration settings insufficient for access to this resource.)'
I don't know how to get a proper response text. I tried searching their websites for examples, but I can't seem to get it. as well I'm not sure if the key is only for scopus but not engineering village which I'm trying to use.
There website is here. https://dev.elsevier.com/index.html?utm_expid=89327795-0.AtRZzToKQ2u1mZEyQ3n7OQ.0&utm_referrer=https%3A%2F%2Fdev.elsevier.com%2Ftecdoc_ev_retrieval_request.html
any help would be appreciated
To get the text out of your response, you need to call the $response->decoded_content method. That will give you the JSON string that you can see in _content in your debug output. I've indented it to make it easier to read.
{
"service-error" : {
"status" : {
"statusCode" : "AUTHENTICATION_ERROR",
"statusText" : "Requestor configuration settings insufficient for access to this resource."
}
}
}
You can use the JSON module to decode this into a Perl data structure.
use JSON 'from_json';
my $res = $ua->request($req);
my $json = from_json( $res->decoded_content );
The error message you get back clearly states that you are not authenticated properly. I've looked at this guide from the documentation you mentioned. It seems that the apiKey URL param works, if you have the right type of account. You should check with whoever made that account for you, or if that was you and you're not sure, the account manager at that service that is working with you. They'll tell you if you are using the right API key, and if this method of authentication works for you.
Since this API also offers to use a custom header X-ELS-APIKey: [apikey] for the authentication I would suggest using that. Your API key is a secret, and you shouldn't share it with anyone. It's like a password. If you put it into the URL, it might show up in log files. But as a header, it does usually not.
This is how you add a custom header to an HTTP request. Make sure you don't have the apiKey URL param any more if you do this.
my $req = HTTP::Request->new( GET => $url ); # no apiKey=123 here!
$req->header( 'X-ELS-APIKey' => 123 );
Now as a last step, you should check the HTTP response code of the response. A 200 (or most other codes that start with 2) means the request was successful. The 403 that you are getting back means unauthorized, which also hints at that you are not authenticated correctly.
Since it seems that this API returns JSON in both success and failure cases, you might need to decode it for both. If you care to examine the failure response, that makes sense. If not, you can skip that part. To do this, use $res->is_success, which is also used in the synopsis of the LWP::UserAgent documentation.
use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request;
use JSON 'from_json';
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new( GET => 'http://api.elsevier.com/content/ev/results?query=stress&database=c&updateNumber=1&pageSize=1' );
$req->header( 'X-ELS-APIKey' => 123 );
if ($req->is_success) {
my $json = from_json( $res->decoded_content );
# ... do stuff with the response
} else {
# something went wrong
}

Attempting to ignore local SSL certificate [duplicate]

I want to access a website where the certificate cannot be verified. I'm using WWW::Mechanize get request. So how would go about ignoring this and continues to connect to the website?
use IO::Socket::SSL qw();
use WWW::Mechanize qw();
my $mech = WWW::Mechanize->new(ssl_opts => {
SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE,
verify_hostname => 0, # this key is likely going to be removed in future LWP >6.04
});
With IO::Socket::SSL earlier than 1.79, see PERL_LWP_SSL_VERIFY_HOSTNAME.
my $mech = WWW::Mechanize->new( 'ssl_opts' => { 'verify_hostname' => 0 } );

Selecting SSL_VERIFY_NONE for SSL_verify_mode

I am trying to create a client connection to an internal ssl site that does not have a certificate and needs to bypass the proxy.
I am able to bypass the proxy, and I am able to connect to the site and create a client connection, however, i am getting this ugly warning:
*******************************************************************
Using the default of SSL_verify_mode of SSL_VERIFY_NONE for client
is deprecated! Please set SSL_verify_mode to SSL_VERIFY_PEER
together with SSL_ca_file|SSL_ca_path for verification.
If you really don't want to verify the certificate and keep the
connection open to Man-In-The-Middle attacks please set
SSL_verify_mode explicitly to SSL_VERIFY_NONE in your application.
*******************************************************************
at C:/strawberry/perl/site/lib/LWP/Protocol/http.pm line 31
My Code:
use RPC::XML::Client;
use XML::Simple;
use LWP::Protocol::https;
$ENV{NO_PROXY} = '10.*';
$ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0;
my $server = RPC::XML::Client->new("$vneUrl/api/index.ice",
ssl_opts => { SSL_verify_mode => 'SSL_VERIFY_NONE',
verify_hostname => 0,
SSL_use_cert => 0x00
},
);
That message is from IO::Socket::SSL, and it refers to the constant SSL_VERIFY_NONE it exports rather than the string 'SSL_VERIFY_NONE'.
Secondly, ssl_opts is an argument of LWP::UserAgent's constructor, not RPC::XML::Client's.
Try:
use IO::Socket::SSL qw( SSL_VERIFY_NONE );
RPC::XML::Client->new($uri,
useragent => [
ssl_opts => {
verify_hostname => 0,
SSL_verify_mode => SSL_VERIFY_NONE,
},
],
);
New version I believe you should set to 0 or 1.
I think this was a bug:
500 SSL_verify_mode must be a number and not a string
From:
$useragent->ssl_opts(SSL_verify_mode=>'SSL_VERIFY_NONE');
To:
$useragent->ssl_opts(SSL_verify_mode=>'0');

Perl AnyEvent::HTTP request using Proxy fails

I tried using the perl module AnyEvent::HTTP to make asynchronous HTTP requests by following this post: http://www.windley.com/archives/2012/03/asynchronous_http_requests_in_perl_using_anyevent.shtml
However, I'm not able to get it working through proxies...
my $request;
my $host = '<userid>:<pswd>#<proxyip>';
my $port = '<proxyport>';
my $headers = { ...
'Accept-Language'=> 'en-us,en;q=0.5',
'Accept-Charset'=> 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Keep-Alive' => 300,
};
$request = http_request(
GET => $url,
timeout => 120, # seconds
headers => $headers,
proxy => [$host, $port],
mymethod
);
$cv->end;
$cv->recv;
I get the following error for the above code (after substituting with authentication details for the proxy)
{
'Reason' => 'No such device or address',
'URL' => 'www.google.com',
'Status' => 595
};
Without the proxy argument of the request, it works. From the CPAN page http://metacpan.org/pod/AnyEvent::HTTP,
595 - errors during connection establishment, proxy handshake
Please help me identify the problem with this code. Thanks!
You cant put your username and password in the $host itself. You need to first encode them in base64 by hand and add the resulting string in the Proxy-Authorization header.
$ echo -n user:pass | openssl enc -a
dXNlcjpwYXNz
Then add this line to your header:
my $request;
my $host = '<proxyip>'; #EDITED
my $port = '<proxyport>';
my $headers = { ...
'Accept-Language'=> 'en-us,en;q=0.5',
'Accept-Charset'=> 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Keep-Alive' => 300,
'Proxy-Authorization'=>'Basic dXNlcjpwYXNz' #EDITED
};
$request = http_request(
GET => $url,
timeout => 120, # seconds
headers => $headers,
proxy => [$host, $port],
mymethod
It should work then!

How to ignore 'Certificate Verify Failed' error in perl?

I want to access a website where the certificate cannot be verified. I'm using WWW::Mechanize get request. So how would go about ignoring this and continues to connect to the website?
use IO::Socket::SSL qw();
use WWW::Mechanize qw();
my $mech = WWW::Mechanize->new(ssl_opts => {
SSL_verify_mode => IO::Socket::SSL::SSL_VERIFY_NONE,
verify_hostname => 0, # this key is likely going to be removed in future LWP >6.04
});
With IO::Socket::SSL earlier than 1.79, see PERL_LWP_SSL_VERIFY_HOSTNAME.
my $mech = WWW::Mechanize->new( 'ssl_opts' => { 'verify_hostname' => 0 } );