Certificates issue with a perl script - perl

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

Related

Get reason for failed LWP::Simple head request

I have migrated my scrilpts from CentOS 7 to 8 and there's a new Perl version. I have the folowing snippet that uses head to check if a URL exists:
#!/bin/perl
use strict;
use warnings;
use LWP::Simple;
my $sitemapurl = "https://www.prosinger.net";
if (head($sitemapurl)) {
...
}
else {
print "The $sitemapurl doesn't exist\n";
exit(1);
}
It now always returns that the URL doesn't exist. I'm quite sure that this has to do something with https (I have perl-LWP-Protocol-https installed), but I'm not sure how to get any feedback information from head method to check what the error code is.
Any ideas?
You can use LWP::UserAgent instead of LWP::Simple, which allows you to get an error message:
my $ua = LWP::UserAgent->new;
my $sitemapurl = "https://www.prosinger.net";
my $req = $ua->head($sitemapurl);
if ($req->is_success) {
...
} else {
die "Could not head($sitemapurl): " . $req->status_line;
}
Running this code prints:
Could not head(https://www.prosinger.net): 403 Forbidden at head.pl line 15.
You can fix this (for this specific website; this will not work for all website) by setting a User-Agent in your LWP::UserAgent object:
my $ua = LWP::UserAgent->new( agent => 'anything seems to work' );
Of interest is the decoded_content method of HTTP::Response that allows you to get the content of the request (you don't need it in that case, but you might later):
my $req = $ua->get(...);
if ($req->is_success) {
my $content = $req->decoded_content;
...
}
Your code that uses LWP::Simple and Dada's version that switches to LWP::UserAgent are basically doing the same thing, except that you can get details of the error when using LWP::UserAgent.
Running the LWP::UserAgent version gives this error:
Could not head(https://www.prosinger.net): 500 Can't connect to www.prosinger.net:443 (SSL connect attempt failed error:2707307E:OCSP routines:OCSP_check_validity:status not yet valid)
And Googling that error message gives this SO answer as the first result. Is it possible that the clocks on your your client machine and the server are out of sync?

Perl LWP::Simple::get($url) does not work for some urls

I am using LWP::Simple::get($url) library to access data from web pages. The problem is that the get function is not working for the below url.
Below is the code snippet:
#!/usr/bin/perl
use LWP::Simple;
use JSON;
use Data::Dumper;
my $url = "https://www.cryptopia.co.nz/api/GetCurrencies";
my $json = get( $url);
die "Could not get $url!" unless defined $json;
my $decoded_json = decode_json($json);
print Dumper($decoded_json);
After running this code it gives the below error:
Could not get https://www.cryptopia.co.nz/api/GetCurrencies!
When I replace the url with : $url = "https://api.coinmarketcap.com/v1/ticker/" it works fine.
Please can you tell me what is the root cause and how I can fix it.
Also the url mentioned in the code snippet worked once and now suddenly it does not work.
This is essentially the same question as this one, only for Perl LWP instead of NodeJS.
The problem is that the target site has a broken setup and is missing an intermediate certificate. This can be seen from the SSLabs report:
This server's certificate chain is incomplete. Grade capped to B.
To work around this you have two secure and one insecure option. The insecure but, unfortunately, often proposed option is to disable all certificate validation. Don't do this because it makes your application vulnerable against man-in-the-middle attacks.
The next option is to have your own trust store which includes all necessary certificates, i.e. both the root CA and also the missing intermediate CA:
use strict;
use warnings;
use LWP::UserAgent;
use IO::Socket::SSL;
my $ua = LWP::UserAgent->new;
$ua->ssl_opts(
SSL_ca_file => 'myca.pem',
# disable OCSP stapling since it results in problems with this site
SSL_ocsp_mode => SSL_OCSP_NO_STAPLE
);
my $resp = $ua->get('https://www.cryptopia.co.nz/api/GetCurrencies');
print $resp->decoded_content;
myca.pem is in this case the concatenation of the PEM representation for the certificates of the intermediate "COMODO RSA Extended Validation Secure Server CA" and the root "COMODO RSA Certification Authority". I've provided it at Pastebin, here.
The third option is to trust this specific leaf certificate only. When used this will trust a server using this certificate, no matter if the certificate is expired, revoked, the hostname does not match the URL or (as in this case) the trust chain cannot be built because of a missing intermediate certificate:
use strict;
use warnings;
use LWP::UserAgent;
use IO::Socket::SSL;
my $ua = LWP::UserAgent->new;
$ua->ssl_opts(
SSL_fingerprint => 'sha256$70bca153ac950b8fa92d20f04dceca929852c42dc1d51bdc3c290df256ae05d3',
SSL_ocsp_mode => SSL_OCSP_NO_STAPLE,
);
my $resp = $ua->get('https://www.cryptopia.co.nz/api/GetCurrencies');
print $resp->decoded_content;
The fingerprint you see here is the one you can also see in the browser when looking at the certificate.

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;

Why does LWP::UserAgent GET request fail with HTTPS?

Here's my code
#!/path/to/perl
use strict;
use LWP::UserAgent;
use HTTP::Request::Common;
use Crypt::SSLeay;
$ENV{HTTPS_PROXY} = 'http://proxy:8080/';
$ENV{HTTPS_DEBUG} = 1;
my $myurl = "https://www.redhat.com";
my $ua = new LWP::UserAgent;
$ua->cookie_jar( {} );
$ua->protocols_allowed( [ 'http','https'] );
$ua->proxy(['http', 'https'], 'http://proxy:8080/');
my $page = $ua->get($myurl);
die "Error $myurl\n ", $page->status_line, "\n Aborting"
unless $page->is_success;
print "Success", $page1->content_type, " document!\n";
It returns
Error at https://www.redhat.com
400 Bad Request
Aborting at test.pl line 30.
what's wrong?
Edit:
Apparently, Its a bug. But the workaround doesn't work for me.
Ha! I got the answer!
1) remove the '/' after the port of ENV{HTTPS_PROXY}
2) Apparently, LWP's proxy system send 'GET' requests instead of CONNECT requests so use Crypt::SSLeay's proxy system by just setting the environment variable and remove the proxy command.
On some systems, e.g. Debian, you need to install the appropriate SSL library for this to work. The error messages on theses systems can sometimes be at bit missleading. I think the Debian package would be libnet-ssleay-perl.
I just uploaded the LWP::Protocol::connect module to CPAN. This module adds the missing HTTP/CONNECT method support to LWP.
use LWP::UserAgent;
$ua = LWP::UserAgent->new();
$ua->proxy('https', 'connect://proxyhost.domain:3128/');
$ua->get('https://www.somesslsite.com');
With this module you can use the regular IO::Socket::SSL implementation for LWP >=6.00.
It looks like your proxy server does not accept HTTPS connections. Have you tried setting it up in your favorite browser and viewing the URL?

Why can't I connect to my CAS server with Perl's AuthCAS?

I'm attempting to use an existing CAS server to authenticate login for a Perl CGI web script and am using the AuthCAS Perl module (v 1.3.1). I can connect to the CAS server to get the service ticket but when I try to connect to validate the ticket my script returns with the following error from the IO::Socket::SSL module:
500 Can't connect to [CAS Server]:443 (Bad hostname '[CAS Server]')
([CAS Server] substituted for real server name)
Symptoms/Tests:
If I type the generated URL for the authentication into the web browser's location bar it returns just fine with the expected XML snippet. So it is not a bad host name.
If I generate a script without using the AuthCAS module but using the IO::Socket::SSL module directly to query the CAS server for validation on the generated service ticket the Perl script will run fine from the command line but not in the browser.
If I add the AuthCAS module into the script in item 2, the script no longer works on the command line and still doesn't work in the browser.
Here is the bare-bones script that produces the error:
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use AuthCAS;
use CGI::Carp qw( fatalsToBrowser );
my $id = $ENV{QUERY_STRING};
my $q = new CGI;
my $target = "http://localhost/cgi-bin/testCAS.cgi";
my $cas = new AuthCAS(casUrl => 'https://cas_server/cas');
if ($id eq ""){
my $login_url = $cas->getServerLoginURL($target);
printf "Location: $login_url\n\n";
exit 0;
} else {
print $q->header();
print "CAS TEST<br>\n";
## When coming back from the CAS server a ticket is provided in the QUERY_STRING
print "QUERY_STRING = " . $id . "</br>\n";
## $ST should contain the received Service Ticket
my $ST = $q->param('ticket');
my $user = $cas->validateST($target, $ST); #### This is what fails
printf "Error: %s\n", &AuthCAS::get_errors() unless (defined $user);
}
Any ideas on where the conflict might be?
The error is coming from the line directly above the snippet Cebjyre quoted namely
$ssl_socket = new IO::Socket::SSL(%ssl_options);
namely the socket creation. All of the input parameters are correct. I had edited the module to put in debug statements and print out all the parameters just before that call and they are all fine. Looks like I'm going to have to dive deeper into the IO::Socket::SSL module.
As usually happens when I post questions like this, I found the problem. It turns out the Crypt::SSLeay module was not installed or at least not up to date. Of course the error messages didn't give me any clues. Updating it and all the problems go away and things are working fine now.
Well, from the module source it looks like that IO::Socket error is coming from get_https2
[...]
unless ($ssl_socket) {
$errors = sprintf "error %s unable to connect https://%s:%s/\n",&IO::Socket::SSL::errstr,$host,$port;
return undef;
}
[...]
which is called by callCAS, which is called by validateST.
One option is to temporarily edit the module file to put some debug statements in if you can, but if I had to guess, I'd say the casUrl you are supplying isn't matching up to the _parse_url regex properly - maybe you have three slashes after the https?