PHP Curl CURLOPT_IPRESOLVE - facebook

I have been working on a facebook application which uses facebook graph API for authentication, recently facebook upgraded to IPv6 and my network does'nt support IPv6 so all of my calls started returning Host is unreachable error, I searched on facebook bugs and found that we can still use force the requests to facebook to use IPv4 using CURL CURLOPT_IPRESOLVE.
Now when I try to send request to Facebook Graph API using curl I get
Notice: Use of undefined constant CURLOPT_IPRESOLVE - assumed 'CURLOPT_IPRESOLVE'
I want to know how can I enable support for this constant or how can I disable IPv6 support in php so that I can send request to Facebook Graph API using IPv4.
My code is
$url = ("https://graph.facebook.com/me/access_token?tokrn");
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_URL, $url);
curl_setopt($c, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
$contents = curl_exec($c);
$err = curl_getinfo($c,CURLINFO_HTTP_CODE);
curl_close($c);
Thanks

Check you curl version
CURLOPT_IPRESOLVE is available since curl 7.10.8
Try this sample code to test
<?php
$version = curl_version();
// These are the bitfields that can be used
// to check for features in the curl build
$bitfields = Array(
'CURL_VERSION_IPV6',
'CURLOPT_IPRESOLVE'
);
foreach($bitfields as $feature)
{
echo $feature . ($version['features'] & constant($feature) ? ' matches' : ' does not match');
echo PHP_EOL;
}
FYI: http://gcov.php.net/PHP_5_3/lcov_html/curl/interface.c.gcov.php

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?

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.

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

LWP HTTPS proxy timing out

I am trying to connect via HTTPS to a site using LWP::Simple. I have set the environment variables both inside of the script and in the shell. I continue to get a 500 Connection Timed Out. I can connect to a HTTP site just fine.
The proxy is letting communication through. I can connect to the HTTPS site through the proxy using curl without a problem.
Any suggestions?
#!/usr/bin/perl
use warnings;
use Net::SSL;
use LWP::UserAgent;
use LWP::Debug qw(+);
use Data::Dumper;
$ENV{PERL_NET_HTTPS_SSL_SOCKET_CLASS} = "Net::SSL";
$ENV{HTTPS_DEBUG} = 1;
$ENV{HTTPS_VERSION} = 2;
my $ua = LWP::UserAgent->new (verify_hostname => 0);
$ua->ssl_opts(verify_hostname => 0,
SSL_verify_mode => 0x00);
$ua->proxy('https' => 'http://x.x.x.x:3128');
print $ua->proxy('https');
print Dumper($ua);
my $response = $ua->get('https://qualys.com/');
print Dumper ($response);
if ($response->is_success) {
print $response->decoded_content; # or whatever
exit(0);
}
else {
print "\nFail:\n";
print $response->status_line ."\n";
exit(1);
}
HTTPS proxy support for LWP is (or at least was until some days ago) broken, at least if you use IO::Socket::SSL, which is the default for LWP versions >=6.0 because it provides better security. It should be much better now with LWP 6.0.6 and LWP::Protocol::https 6.0.6 which were released few days ago. If you cannot upgrade you might try using Net::SSLGlue::LWP which patches LWP for better https proxy support.

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

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.