Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

WWW::Curl::Easy CAPATH

Status
Not open for further replies.

Kirsle

Programmer
Jan 21, 2006
1,179
US
I'm wondering if anyone can provide a little insight to this problem I'm having on one of my servers.

I'm using smokeping to monitor the latency time on various web pages on different servers. It used to work fine until about a month ago. Now, all the webpages that are requested over HTTP have their statistics and graphs generated just fine, but ones over SSL have blank graphs and don't output any data.

I eventually narrowed it down to this: the server they're monitoring had its SSL certificate modified recently (either regenerated or updated or something). The cert is signed by UserFirst, which in turn is signed by AddTrust.

At the command line, if I run a regular curl command on one of the HTTPS URLs:

Code:
$ curl [URL unfurl="true"]https://.../cart/content/dedicated/Webmaster/Plan1[/URL]
curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
More details here: [URL unfurl="true"]http://curl.haxx.se/docs/sslcerts.html[/URL]

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). The default
 bundle is named curl-ca-bundle.crt; you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

So, if I try it with the -k option:

Code:
$ curl -k [URL unfurl="true"]https://.../cart/content/dedicated/Webmaster/Plan1[/URL]

It works and gets me the page requested. If I modify the Perl module that does this request for smokeping (and it uses and set this line:

Code:
$curl->setopt(CURLOPT_SSL_VERIFYPEER, 0);

Then it also works. However, it's not a very good solution to just turn off SSL verification when it *should* be working anyway.

I read on curl's site to tell it to use the cabundle that has the cert for your certificate authority. I downloaded the cabundle from the server curl's hitting. However, trying to run the `curl` command using this cabundle doesn't help.

When using the Mozilla cabundles file, the request goes through fine. I eventually narrowed it down to: it wants the AddTrust ca cert. So I ended up making an "addtrust.pem" and added just the AddTrust cert from the Mozilla file that it wants and the request goes through fine:

Code:
$ curl --cacert addtrust.pem [URL unfurl="true"]https://.../cart/content/dedicated/Webmaster/Plan1[/URL]

So, having gotten the cacert file working, I went back to put it into my Perl code:

Code:
$curl->setopt(CURLOPT_CAPATH, "/home/smoke/addtrust.pem");

Adding this line had no effect on the Perl script's ability to run. I tried giving it a relative path, absolute path, path to a file that doesn't exist, nothing makes a difference (although knows if I misspell the option name, which I did on purpose to verify that it knows I got a valid option name). It always just dies with the error:

Code:
$ perl ~/curltest.pl 
Failed ::SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

So at the end of my adventure, the only thing stopping me from solving this problem is that for some reason, setting CURLOPT_CAPATH in the Perl script is *not* being equivalent to "--cacert" on the command line, even though it should be. Does anyone have any experience with and might know if I'm doing something wrong?

Here's the full source to my test script if it'll help:

Code:
# note: certain things are censored out
use strict;
use warnings;
use [URL unfurl="true"]WWW::Curl::Easy;[/URL]

&pingone (undef, {
	vars => {
		cookiefile => "./cookies",
		output     => "./testout.out",
		url        => "[URL unfurl="true"]https://.../cart/content/dedicated/Webmaster/Plan1",[/URL]
	},
});

sub pings {
	return 1;
}

sub pingone {
    my $self = shift;
    my $target = shift;

    # my $binary = $self->{properties}{binary};
    my $cookiefile = $target->{'vars'}{'cookiefile'};
    my $url = $target->{'vars'}{'url'};
    my $output  = $target->{'vars'}{'output'};
    my $count = pings($target); # the number of pings for this targets
    $count = 1;

    # ping one target

    # execute a command and parse its output
    # you should return a sorted array of the measured latency times
    # it could go something like this:

    my @times;

   my $curl= [URL unfurl="true"]WWW::Curl::Easy->new()[/URL] or die "curl init failed!\n";
   $curl->setopt(CURLOPT_URL, $url);
   $curl->setopt(CURLOPT_COOKIEJAR,"$cookiefile.jar");
   $curl->setopt(CURLOPT_COOKIEFILE,$cookiefile);
   $curl->setopt(CURLOPT_COOKIE, "entropy-support-login=xyzzy\@xyzzy.com; view=standard;");
   $curl->setopt(CURLOPT_CAPATH, "/home/smoke/addtrust.pem");


   sub header_callback {
       my ($chunk,$context)=@_;
       push @{$context}, $chunk;
       return length($chunk); # OK
   }

   sub body_callback {
       my ($chunk,$context)=@_;
       push @{$context}, $chunk;
       return length($chunk); # OK
   }

   my @headers=();
   my @body;

#  if(defined($output) && (length($output) > 0)) {
      $curl->setopt(CURLOPT_HEADERFUNCTION, \&header_callback );
      $curl->setopt(CURLOPT_WRITEHEADER, \@headers );
      $curl->setopt(CURLOPT_WRITEFUNCTION, \&body_callback);
      $curl->setopt(CURLOPT_FILE, \@body);
#  }
   my $i = 1;
    for (1..$count) {

    #        open(P, "$cmd 2>&1 |") or croak("fork: $!");
    #        while (<P>) {
    #                /time: (\d+\.\d+)/ and push @times, $1;
    #        }
    #        close P;
      my $starttime = time;
      if ($curl->perform() != 0) {
          print "Failed ::".$curl->errbuf."\n";
      };
      my $endtime = time;
      $curl->curl_easy_cleanup();
      push @times, sprintf('%0.4f', $endtime - $starttime );
      if(defined($output) && (length($output) > 0)) {
         if($i == 1) {
            open(OUTFILE, ">$output");
            foreach my $line (@headers) {
               print OUTFILE $line;
            }
            print OUTFILE "\n\n";
            foreach my $line (@body) {
               print OUTFILE $line;
            }
            close(OUTFILE);
         }
      }
      @headers = ();
      @body = ();
      $i++;
    }
   while (scalar(@times) < pings($target)) {
      push @times, $times[0];
   }
    return @times;
}

-------------
Cuvou.com | My personal homepage
Project Fearless | My web blog
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top