1

I am trying to access xenapi with the following perl script. The "http" version seem to work, but the "https" version doesn't. The code:

#!/usr/bin/perl
use 5.20.0;
use RPC::XML::Client;
use Data::Dumper;
use IO::Socket::SSL qw( SSL_VERIFY_NONE );
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
$ENV{HTTPS_DEBUG} = 1;
$Data::Dumper::Indent   = 1;
$Data::Dumper::Sortkeys = 1;

use Xen::API;

my $user='Gordon';
my $passwd='Freeman';
my $xen = RPC::XML::Client->new("https://xen1.blackmesa.gov",
    ssl_opts =>    {  
        verify_hostname => 0,
        SSL_verify_mode => SSL_VERIFY_NONE
    },);

my $test = $xen->simple_request('session.login_with_password',$user,$passwd);
say '$RPC::XML::ERROR = '.Dumper($RPC::XML::ERROR);
say '$xen = '.Dumper($xen);

here is the output of the script:

$RPC::XML::ERROR = $VAR1 = 'RPC::XML::Client::simple_request: RPC::XML::Client::send_request: HTTP server error: Can\'t connect to xen1.blackmesa.gov:443 (certificate verify failed)';

$xen = $VAR1 = bless( {
  '__compress' => 'deflate',
  '__compress_re' => qr/deflate/,
  '__compress_requests' => 0,
  '__compress_thresh' => 4096,
  '__message_file_thresh' => 1048576,
  '__message_temp_dir' => '',
  '__parser' => bless( [
    []
  ], 'RPC::XML::Parser::XMLParser' ),
  '__request' => bless( {
    '_content' => '',
    '_headers' => bless( {
      'accept-encoding' => 'deflate',
      'content-type' => 'text/xml'
    }, 'HTTP::Headers' ),
    '_method' => 'POST',
    '_protocol' => 'HTTP/1.1',
    '_uri' => bless( do{\(my $o = 'https://xen1.blackmesa.gov')}, 'URI::https' )
  }, 'HTTP::Request' ),
  '__request_as_string' => undef,
  '__useragent' => bless( {
    'def_headers' => bless( {
      'user-agent' => 'RPC::XML::Client/1.44 libwww-perl/6.52'
    }, 'HTTP::Headers' ),
    'handlers' => {
      'response_header' => bless( [
        { 
          'callback' => sub { "DUMMY" },
          'line' => '/usr/share/perl5/LWP/UserAgent.pm:768',
          'm_media_type' => 'html',
          'owner' => 'LWP::UserAgent::parse_head'
        }
      ], 'HTTP::Config' )
    },
    'local_address' => undef,
    'max_redirect' => 7,
    'max_size' => undef,
    'no_proxy' => [],
    'protocols_allowed' => undef,
    'protocols_forbidden' => undef,
    'proxy' => {},
    'requests_redirectable' => [
      'GET',
      'HEAD'
    ],
    'send_te' => 1,
    'show_progress' => undef,
    'ssl_opts' => {
      'verify_hostname' => '0'
    },
    'timeout' => 180,
    'use_eval' => 1
  }, 'LWP::UserAgent' ),
  'ssl_opts' => {
    'SSL_verify_mode' => 0,
    'verify_hostname' => 0
  }
}, 'RPC::XML::Client' );

Any hint how to make the code work? It is suspicious that ssl_opts are actually present 2 times the dump of $xen.

The following python script seem to work, so I assume that the Xenapi over https is working.

import XenAPI

session = XenAPI.Session('https://xen1.blackmesa.gov:443',ignore_ssl=True)
session.xenapi.login_with_password('Gordon', 'Freeman', "2.3", "test")
hosts = session.xenapi.host.get_all()
for host in hosts:
        vms = session.xenapi.host.get_resident_VMs(host)
        print (vms)

without ignore_ssl=True in the python script I get the following error:

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: EE certificate key too weak (_ssl.c:1123)

this is the relevant output of openssl s_client -showcerts -connect xen1.blackmesa.gov

Peer signing digest: SHA512
Peer signature type: RSA
Server Temp Key: ECDH, P-384, 384 bits
---
SSL handshake has read 1134 bytes and written 532 bytes
Verification error: self signed certificate
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-SHA384
mestia
  • 450
  • 2
  • 7
  • 1
    *"$test is "undef" when I run this code"* According to the [docs](https://metacpan.org/pod/RPC::XML::Client) : "If the return value is undef, an error has occurred and simple_request has placed the error message in the global variable $RPC::XML::ERROR". Can you show the value of `$RPC::XML::ERROR` ? – Håkon Hægland Feb 10 '21 at 14:15
  • This helps a lot! thank you! I've updated the script with the Dumper output. The error message is "certificate verify failed", the strange thing is that in Dumper($xen) the ssl_opts are present 2 times. Looks like 'SSL_verify_mode' => 0, is not passes to LWP::UserAgent – mestia Feb 10 '21 at 17:10
  • Does [this](https://stackoverflow.com/a/47668190/2173773) answer help? – Håkon Hægland Feb 10 '21 at 21:01
  • Thank you for the link, it is definitely useful. I think I found a solution and will add it to the answer. – mestia Feb 11 '21 at 16:52

1 Answers1

1

I've managed to solve the problem the following way:

  1. get the certificate from the server and save it to a file:

openssl s_client -showcerts -connect <server>:443 </dev/null 2>/dev/null|openssl x509 -outform PEM >mycertfile.pem

  1. set HTTPS_CA_FILE or PERL_LWP_SSL_CA_FILE environment variables to the mycertfile.pem location, both variables are described in the LWP docs.

  2. since in my case the server was using a weak key, I had to set the SECLEVEL to 1 in /etc/ssl/openssl.conf: CipherString = DEFAULT@SECLEVEL=1

The final code looks like that:

use RPC::XML::Client;
use Xen::API;
$ENV{HTTPS_CA_FILE} = '<location_of_mycertfile.pem>';
my $xen = RPC::XML::Client->new("https://xen1.blackmesa.gov")
my $test = $xen->simple_request('session.login_with_password',"user","passwd");
print $test->{'Status'} if $test;

mestia
  • 450
  • 2
  • 7